diff --git a/docs/api.md b/docs/api.md
index 8b08d79495..ce7e140ee0 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -3642,19 +3642,229 @@ This module provides queries related to events.
## DB API: feature related queries
This module provides queries for features.
+
+* [DB API: feature related queries](#module_DB API_ feature related queries)
+ * [~getFeaturesByDeviceTypeRefs(db, deviceTypeRefs, endpointTypeRef)](#module_DB API_ feature related queries..getFeaturesByDeviceTypeRefs) ⇒
+ * [~evaluateConformanceExpression(expression, elementMap)](#module_DB API_ feature related queries..evaluateConformanceExpression) ⇒
+ * [~evaluateBooleanExpression(expr)](#module_DB API_ feature related queries..evaluateConformanceExpression..evaluateBooleanExpression)
+ * [~evaluateWithParentheses(expr)](#module_DB API_ feature related queries..evaluateConformanceExpression..evaluateWithParentheses)
+ * [~checkMissingTerms(expression, elementMap)](#module_DB API_ feature related queries..checkMissingTerms) ⇒
+ * [~filterElementsContainingDesc(elements)](#module_DB API_ feature related queries..filterElementsContainingDesc) ⇒
+ * [~filterRelatedDescElements(elements, featureCode)](#module_DB API_ feature related queries..filterRelatedDescElements) ⇒
+ * [~generateWarningMessage(featureData, endpointId, missingTerms, featureMap, descElements)](#module_DB API_ feature related queries..generateWarningMessage) ⇒
+ * [~checkElementConformance(elements, featureMap, featureData, endpointId)](#module_DB API_ feature related queries..checkElementConformance) ⇒
+ * [~filterElementsToUpdate(elements, elementMap, featureCode)](#module_DB API_ feature related queries..filterElementsToUpdate) ⇒
+ * [~getOutdatedElementWarning(featureData, elements, elementMap)](#module_DB API_ feature related queries..getOutdatedElementWarning) ⇒
+ * [~processElements(elementType)](#module_DB API_ feature related queries..getOutdatedElementWarning..processElements)
+ * [~filterRequiredElements(elements, elementMap, featureMap)](#module_DB API_ feature related queries..filterRequiredElements) ⇒
+ * [~checkIfConformanceDataExist(db)](#module_DB API_ feature related queries..checkIfConformanceDataExist) ⇒
+
-### DB API: feature related queries~getFeaturesByDeviceTypeRefs(db, deviceTypeRefs) ⇒
-Get all device type features associated with a list of device type refs
+### DB API: feature related queries~getFeaturesByDeviceTypeRefs(db, deviceTypeRefs, endpointTypeRef) ⇒
+Get all device type features associated with a list of device type refs and an endpoint.
+Join ENDPOINT_TYPE_ATTRIBUTE and ATTRIBUTE table to get featureMap attribute associated with the feature,
+so the frontend could get and set featureMap bit easier.
+Only return features with cluster on the side specified in the device type.
**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
**Returns**: All feature information and device type conformance
-with associated device type and cluster details
+with associated device type, cluster, and featureMap attribute details
| Param | Type |
| --- | --- |
| db | \*
|
| deviceTypeRefs | \*
|
+| endpointTypeRef | \*
|
+
+
+
+### DB API: feature related queries~evaluateConformanceExpression(expression, elementMap) ⇒
+Evaluate the value of a boolean conformance expression that includes terms and operators.
+A term can be an attribute, command, event, feature, or conformance abbreviation.
+Operators include AND (&), OR (|), and NOT (!).
+The '[]' indicates optional conformance if the expression inside true.
+Expression containing comma means otherwise conformance. See spec for details.
+Examples of conformance expression: 'A & (!B | C)', 'A & B, [!C]'
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: 'mandatory', 'optional', 'provisional', or 'notSupported'
+
+| Param | Type |
+| --- | --- |
+| expression | \*
|
+| elementMap | \*
|
+
+
+* [~evaluateConformanceExpression(expression, elementMap)](#module_DB API_ feature related queries..evaluateConformanceExpression) ⇒
+ * [~evaluateBooleanExpression(expr)](#module_DB API_ feature related queries..evaluateConformanceExpression..evaluateBooleanExpression)
+ * [~evaluateWithParentheses(expr)](#module_DB API_ feature related queries..evaluateConformanceExpression..evaluateWithParentheses)
+
+
+
+#### evaluateConformanceExpression~evaluateBooleanExpression(expr)
+helper function to evaluate a single boolean expression
+
+**Kind**: inner method of [evaluateConformanceExpression
](#module_DB API_ feature related queries..evaluateConformanceExpression)
+
+| Param | Type |
+| --- | --- |
+| expr | \*
|
+
+
+
+#### evaluateConformanceExpression~evaluateWithParentheses(expr)
+helper function to process parentheses and evaluate inner expressions first
+
+**Kind**: inner method of [evaluateConformanceExpression
](#module_DB API_ feature related queries..evaluateConformanceExpression)
+
+| Param | Type |
+| --- | --- |
+| expr | \*
|
+
+
+
+### DB API: feature related queries~checkMissingTerms(expression, elementMap) ⇒
+Check if any terms in the expression are neither a key in the elementMap nor an abbreviation.
+If so, it means the conformance depends on terms with unknown values and changes are not allowed.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: all missing terms in an array
+
+| Param | Type |
+| --- | --- |
+| expression | \*
|
+| elementMap | \*
|
+
+
+
+### DB API: feature related queries~filterElementsContainingDesc(elements) ⇒
+Filter an array of elements by if any element has conformance containing the term 'desc'.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: elements with conformance containing 'desc'
+
+| Param | Type |
+| --- | --- |
+| elements | \*
|
+
+
+
+### DB API: feature related queries~filterRelatedDescElements(elements, featureCode) ⇒
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: elements with conformance containing 'desc' and the feature code
+
+| Param | Type |
+| --- | --- |
+| elements | \*
|
+| featureCode | \*
|
+
+
+
+### DB API: feature related queries~generateWarningMessage(featureData, endpointId, missingTerms, featureMap, descElements) ⇒
+Generate a warning message after processing conformance of the updated device type feature.
+Set flags to decide whether to show a popup warning or disable changes in the frontend.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: warning message array, disableChange flag, and displayWarning flag
+
+| Param | Type |
+| --- | --- |
+| featureData | \*
|
+| endpointId | \*
|
+| missingTerms | \*
|
+| featureMap | \*
|
+| descElements | \*
|
+
+
+
+### DB API: feature related queries~checkElementConformance(elements, featureMap, featureData, endpointId) ⇒
+Check if elements need to be updated for correct conformance if featureData provided.
+Otherwise, check if elements are required or unsupported by their conformance.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: attributes, commands, and events to update, with warnings if featureData provided;
+required and unsupported attributes, commands, and events, with warnings if not.
+
+| Param | Type | Default |
+| --- | --- | --- |
+| elements | \*
| |
+| featureMap | \*
| |
+| featureData | \*
|
|
+| endpointId | \*
|
|
+
+
+
+### DB API: feature related queries~filterElementsToUpdate(elements, elementMap, featureCode) ⇒
+Return attributes, commands, or events to be updated satisfying:
+(1) its conformance includes feature code of the updated feature
+(2) it has mandatory conformance but it is not enabled, OR,
+ it is has notSupported conformance but it is enabled
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: elements that should be updated
+
+| Param | Type |
+| --- | --- |
+| elements | \*
|
+| elementMap | \*
|
+| featureCode | \*
|
+
+
+
+### DB API: feature related queries~getOutdatedElementWarning(featureData, elements, elementMap) ⇒
+Get warnings for element requirements that are outdated after a feature update.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: array of outdated element warnings
+
+| Param | Type |
+| --- | --- |
+| featureData | \*
|
+| elements | \*
|
+| elementMap | \*
|
+
+
+
+#### getOutdatedElementWarning~processElements(elementType)
+Build substrings of outdated warnings and add to returned array if:
+(1) the element conformance includes the feature code
+(2) the element conformance has changed after the feature update
+
+**Kind**: inner method of [getOutdatedElementWarning
](#module_DB API_ feature related queries..getOutdatedElementWarning)
+
+| Param | Type |
+| --- | --- |
+| elementType | \*
|
+
+
+
+### DB API: feature related queries~filterRequiredElements(elements, elementMap, featureMap) ⇒
+Filter required and unsupported elements based on their conformance and generate warnings.
+An element is required if it conforms to element(s) in elementMap and has 'mandatory' conform.
+An element is unsupported if it conforms to element(s) in elementMap and has 'notSupported' conform.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: required and not supported elements with warnings
+
+| Param | Type |
+| --- | --- |
+| elements | \*
|
+| elementMap | \*
|
+| featureMap | \*
|
+
+
+
+### DB API: feature related queries~checkIfConformanceDataExist(db) ⇒
+Check if any non-empty conformance data exist in ATTRIBUTE, COMMAND,
+and DEVICE_TYPE_FEATURE table.
+
+**Kind**: inner method of [DB API: feature related queries
](#module_DB API_ feature related queries)
+**Returns**: boolean value indicating if conformance data exists
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
@@ -14372,6 +14582,9 @@ This module provides the API to access zcl specific information.
* [~httpGetSessionKeyValues(db)](#module_REST API_ user data..httpGetSessionKeyValues) ⇒
* [~httpGetEndpointIds(db)](#module_REST API_ user data..httpGetEndpointIds) ⇒
* [~httpGetDeviceTypeFeatures(db)](#module_REST API_ user data..httpGetDeviceTypeFeatures) ⇒
+ * [~getEndpointTypeElements(db, endpointTypeClusterId, deviceTypeClusterId)](#module_REST API_ user data..getEndpointTypeElements) ⇒
+ * [~httpPostCheckConformOnFeatureUpdate(db)](#module_REST API_ user data..httpPostCheckConformOnFeatureUpdate) ⇒
+ * [~httpGetRequiredElements(db)](#module_REST API_ user data..httpGetRequiredElements) ⇒
* [~httpGetSessionNotifications(db)](#module_REST API_ user data..httpGetSessionNotifications) ⇒
* [~httpDeleteSessionNotification(db)](#module_REST API_ user data..httpDeleteSessionNotification) ⇒
* [~httpGetPackageNotifications(db)](#module_REST API_ user data..httpGetPackageNotifications) ⇒
@@ -14401,6 +14614,9 @@ This module provides the API to access zcl specific information.
* [~httpDeleteSessionPackage(db)](#module_REST API_ user data..httpDeleteSessionPackage) ⇒
* [~httpPostDuplicateEndpoint(db)](#module_REST API_ user data..httpPostDuplicateEndpoint) ⇒
* [~httpPostDuplicateEndpointType(db)](#module_REST API_ user data..httpPostDuplicateEndpointType) ⇒
+ * [~httpPatchUpdateBitOfFeatureMapAttribute(db)](#module_REST API_ user data..httpPatchUpdateBitOfFeatureMapAttribute) ⇒
+ * [~httpGetConformDataExists(db)](#module_REST API_ user data..httpGetConformDataExists) ⇒
+ * [~httpPostRequiredElementWarning(db)](#module_REST API_ user data..httpPostRequiredElementWarning) ⇒
* [~duplicateEndpointTypeClusters(db, oldEndpointTypeId, newEndpointTypeId)](#module_REST API_ user data..duplicateEndpointTypeClusters)
@@ -14454,6 +14670,45 @@ HTTP GET: device type features
| --- | --- |
| db | \*
|
+
+
+### REST API: user data~getEndpointTypeElements(db, endpointTypeClusterId, deviceTypeClusterId) ⇒
+Get all attributes, commands and events in an endpoint type cluster.
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: elements object containing all attributes, commands and events
+in an endpoint type cluster
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+| endpointTypeClusterId | \*
|
+| deviceTypeClusterId | \*
|
+
+
+
+### REST API: user data~httpPostCheckConformOnFeatureUpdate(db) ⇒
+HTTP POST: elements to be updated after toggle a device type feature
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: callback for the express uri registration
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
+
+
+### REST API: user data~httpGetRequiredElements(db) ⇒
+HTTP GET: required and unsupported cluster elements based on conformance
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: callback for the express uri registration
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
### REST API: user data~httpGetSessionNotifications(db) ⇒
@@ -14800,6 +15055,42 @@ Creating a duplicate for endpoint-type and endpoint-type-attributes
| --- | --- |
| db | \*
|
+
+
+### REST API: user data~httpPatchUpdateBitOfFeatureMapAttribute(db) ⇒
+Update feature map attribute with given new value
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: status of the update
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
+
+
+### REST API: user data~httpGetConformDataExists(db) ⇒
+Check if conformance data exists in the database
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: boolean value of data exist or not
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
+
+
+### REST API: user data~httpPostRequiredElementWarning(db) ⇒
+Set warning for the required element, and delete its existing warning if any.
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: response of setting the warning notification
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
### REST API: user data~duplicateEndpointTypeClusters(db, oldEndpointTypeId, newEndpointTypeId)
@@ -15630,6 +15921,9 @@ This module provides the REST API to the user specific data.
* [~httpGetSessionKeyValues(db)](#module_REST API_ user data..httpGetSessionKeyValues) ⇒
* [~httpGetEndpointIds(db)](#module_REST API_ user data..httpGetEndpointIds) ⇒
* [~httpGetDeviceTypeFeatures(db)](#module_REST API_ user data..httpGetDeviceTypeFeatures) ⇒
+ * [~getEndpointTypeElements(db, endpointTypeClusterId, deviceTypeClusterId)](#module_REST API_ user data..getEndpointTypeElements) ⇒
+ * [~httpPostCheckConformOnFeatureUpdate(db)](#module_REST API_ user data..httpPostCheckConformOnFeatureUpdate) ⇒
+ * [~httpGetRequiredElements(db)](#module_REST API_ user data..httpGetRequiredElements) ⇒
* [~httpGetSessionNotifications(db)](#module_REST API_ user data..httpGetSessionNotifications) ⇒
* [~httpDeleteSessionNotification(db)](#module_REST API_ user data..httpDeleteSessionNotification) ⇒
* [~httpGetPackageNotifications(db)](#module_REST API_ user data..httpGetPackageNotifications) ⇒
@@ -15659,6 +15953,9 @@ This module provides the REST API to the user specific data.
* [~httpDeleteSessionPackage(db)](#module_REST API_ user data..httpDeleteSessionPackage) ⇒
* [~httpPostDuplicateEndpoint(db)](#module_REST API_ user data..httpPostDuplicateEndpoint) ⇒
* [~httpPostDuplicateEndpointType(db)](#module_REST API_ user data..httpPostDuplicateEndpointType) ⇒
+ * [~httpPatchUpdateBitOfFeatureMapAttribute(db)](#module_REST API_ user data..httpPatchUpdateBitOfFeatureMapAttribute) ⇒
+ * [~httpGetConformDataExists(db)](#module_REST API_ user data..httpGetConformDataExists) ⇒
+ * [~httpPostRequiredElementWarning(db)](#module_REST API_ user data..httpPostRequiredElementWarning) ⇒
* [~duplicateEndpointTypeClusters(db, oldEndpointTypeId, newEndpointTypeId)](#module_REST API_ user data..duplicateEndpointTypeClusters)
@@ -15712,6 +16009,45 @@ HTTP GET: device type features
| --- | --- |
| db | \*
|
+
+
+### REST API: user data~getEndpointTypeElements(db, endpointTypeClusterId, deviceTypeClusterId) ⇒
+Get all attributes, commands and events in an endpoint type cluster.
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: elements object containing all attributes, commands and events
+in an endpoint type cluster
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+| endpointTypeClusterId | \*
|
+| deviceTypeClusterId | \*
|
+
+
+
+### REST API: user data~httpPostCheckConformOnFeatureUpdate(db) ⇒
+HTTP POST: elements to be updated after toggle a device type feature
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: callback for the express uri registration
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
+
+
+### REST API: user data~httpGetRequiredElements(db) ⇒
+HTTP GET: required and unsupported cluster elements based on conformance
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: callback for the express uri registration
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
### REST API: user data~httpGetSessionNotifications(db) ⇒
@@ -16058,6 +16394,42 @@ Creating a duplicate for endpoint-type and endpoint-type-attributes
| --- | --- |
| db | \*
|
+
+
+### REST API: user data~httpPatchUpdateBitOfFeatureMapAttribute(db) ⇒
+Update feature map attribute with given new value
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: status of the update
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
+
+
+### REST API: user data~httpGetConformDataExists(db) ⇒
+Check if conformance data exists in the database
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: boolean value of data exist or not
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
+
+
+### REST API: user data~httpPostRequiredElementWarning(db) ⇒
+Set warning for the required element, and delete its existing warning if any.
+
+**Kind**: inner method of [REST API: user data
](#module_REST API_ user data)
+**Returns**: response of setting the warning notification
+
+| Param | Type |
+| --- | --- |
+| db | \*
|
+
### REST API: user data~duplicateEndpointTypeClusters(db, oldEndpointTypeId, newEndpointTypeId)
@@ -19763,8 +20135,8 @@ This module provides the APIs for dotdot Loading
* [~parseManufacturerData(db, ctx)](#module_Loader API_ Loader APIs..parseManufacturerData) ⇒
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
- * [~parseFeatureConformance(operand)](#module_Loader API_ Loader APIs..parseFeatureConformance) ⇒
- * [~parseAndOrConformanceTerms(operand, joinChar)](#module_Loader API_ Loader APIs..parseAndOrConformanceTerms) ⇒
+ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
+ * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
@@ -21115,10 +21487,14 @@ Key/velues of the object itself, end up in CODE/LABEL combinations.
| packageId | \*
|
| featureFlags | \*
|
-
+
+
+### Loader API: Loader APIs~parseConformanceFromXML(operand) ⇒
+Parses conformance from XML data.
+The conformance could come from features, attributes, commands, or events
-### Loader API: Loader APIs~parseFeatureConformance(operand) ⇒
-Parses feature conformance or an operand in feature conformance recursively from xml data.
+Call recursive helper function to parse conformance only if the conformance exists.
+Otherwise, return empty string directly
An example of parsing the conformance of 'User' device type feature:
@@ -21133,7 +21509,7 @@ Input operand from xml data:
{ "feature": [
{ "$": {"name": "PIN"}},
{ "$": {"name": "RID"}},
- { "$": {"name": "FPG"}},
+ { "$": {"name": "FGP"}},
{ "$": {"name": "FACE"}}
]
}
@@ -21144,28 +21520,32 @@ Input operand from xml data:
]
}
-Output device type feature conformance string:
- "Matter & (PIN | RID | FPG | FACE)"
+Output conformance string:
+ "Matter & (PIN | RID | FGP | FACE)"
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: The feature conformance string.
+**Returns**: The conformance string
-| Param | Type | Description |
-| --- | --- | --- |
-| operand | \*
| The operand to be parsed. |
+| Param | Type |
+| --- | --- |
+| operand | \*
|
+
+
-
+### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
+helper function to parse conformance or an operand in conformance recursively
-### Loader API: Loader APIs~parseAndOrConformanceTerms(operand, joinChar) ⇒
-Helper function to parse andTerm or orTerm from xml data
+The baseLevelTerms variable include terms that can not have nested terms.
+When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: feature conformance string
+**Returns**: The conformance string.
-| Param | Type |
-| --- | --- |
-| operand | \*
|
-| joinChar | \*
|
+| Param | Type | Default |
+| --- | --- | --- |
+| operand | \*
| |
+| depth | \*
| 0
|
+| parentJoinChar | \*
| |
@@ -21589,8 +21969,8 @@ This module provides the APIs for new data model loading
* [~parseManufacturerData(db, ctx)](#module_Loader API_ Loader APIs..parseManufacturerData) ⇒
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
- * [~parseFeatureConformance(operand)](#module_Loader API_ Loader APIs..parseFeatureConformance) ⇒
- * [~parseAndOrConformanceTerms(operand, joinChar)](#module_Loader API_ Loader APIs..parseAndOrConformanceTerms) ⇒
+ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
+ * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
@@ -22941,10 +23321,14 @@ Key/velues of the object itself, end up in CODE/LABEL combinations.
| packageId | \*
|
| featureFlags | \*
|
-
+
+
+### Loader API: Loader APIs~parseConformanceFromXML(operand) ⇒
+Parses conformance from XML data.
+The conformance could come from features, attributes, commands, or events
-### Loader API: Loader APIs~parseFeatureConformance(operand) ⇒
-Parses feature conformance or an operand in feature conformance recursively from xml data.
+Call recursive helper function to parse conformance only if the conformance exists.
+Otherwise, return empty string directly
An example of parsing the conformance of 'User' device type feature:
@@ -22959,7 +23343,7 @@ Input operand from xml data:
{ "feature": [
{ "$": {"name": "PIN"}},
{ "$": {"name": "RID"}},
- { "$": {"name": "FPG"}},
+ { "$": {"name": "FGP"}},
{ "$": {"name": "FACE"}}
]
}
@@ -22970,28 +23354,32 @@ Input operand from xml data:
]
}
-Output device type feature conformance string:
- "Matter & (PIN | RID | FPG | FACE)"
+Output conformance string:
+ "Matter & (PIN | RID | FGP | FACE)"
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: The feature conformance string.
+**Returns**: The conformance string
-| Param | Type | Description |
-| --- | --- | --- |
-| operand | \*
| The operand to be parsed. |
+| Param | Type |
+| --- | --- |
+| operand | \*
|
-
+
-### Loader API: Loader APIs~parseAndOrConformanceTerms(operand, joinChar) ⇒
-Helper function to parse andTerm or orTerm from xml data
+### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
+helper function to parse conformance or an operand in conformance recursively
+
+The baseLevelTerms variable include terms that can not have nested terms.
+When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: feature conformance string
+**Returns**: The conformance string.
-| Param | Type |
-| --- | --- |
-| operand | \*
|
-| joinChar | \*
|
+| Param | Type | Default |
+| --- | --- | --- |
+| operand | \*
| |
+| depth | \*
| 0
|
+| parentJoinChar | \*
| |
@@ -23415,8 +23803,8 @@ This module provides the APIs for ZCL/Data-Model loading.
* [~parseManufacturerData(db, ctx)](#module_Loader API_ Loader APIs..parseManufacturerData) ⇒
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
- * [~parseFeatureConformance(operand)](#module_Loader API_ Loader APIs..parseFeatureConformance) ⇒
- * [~parseAndOrConformanceTerms(operand, joinChar)](#module_Loader API_ Loader APIs..parseAndOrConformanceTerms) ⇒
+ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
+ * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
@@ -24767,10 +25155,14 @@ Key/velues of the object itself, end up in CODE/LABEL combinations.
| packageId | \*
|
| featureFlags | \*
|
-
+
-### Loader API: Loader APIs~parseFeatureConformance(operand) ⇒
-Parses feature conformance or an operand in feature conformance recursively from xml data.
+### Loader API: Loader APIs~parseConformanceFromXML(operand) ⇒
+Parses conformance from XML data.
+The conformance could come from features, attributes, commands, or events
+
+Call recursive helper function to parse conformance only if the conformance exists.
+Otherwise, return empty string directly
An example of parsing the conformance of 'User' device type feature:
@@ -24785,7 +25177,7 @@ Input operand from xml data:
{ "feature": [
{ "$": {"name": "PIN"}},
{ "$": {"name": "RID"}},
- { "$": {"name": "FPG"}},
+ { "$": {"name": "FGP"}},
{ "$": {"name": "FACE"}}
]
}
@@ -24796,28 +25188,32 @@ Input operand from xml data:
]
}
-Output device type feature conformance string:
- "Matter & (PIN | RID | FPG | FACE)"
+Output conformance string:
+ "Matter & (PIN | RID | FGP | FACE)"
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: The feature conformance string.
+**Returns**: The conformance string
-| Param | Type | Description |
-| --- | --- | --- |
-| operand | \*
| The operand to be parsed. |
+| Param | Type |
+| --- | --- |
+| operand | \*
|
-
+
-### Loader API: Loader APIs~parseAndOrConformanceTerms(operand, joinChar) ⇒
-Helper function to parse andTerm or orTerm from xml data
+### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
+helper function to parse conformance or an operand in conformance recursively
+
+The baseLevelTerms variable include terms that can not have nested terms.
+When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: feature conformance string
+**Returns**: The conformance string.
-| Param | Type |
-| --- | --- |
-| operand | \*
|
-| joinChar | \*
|
+| Param | Type | Default |
+| --- | --- | --- |
+| operand | \*
| |
+| depth | \*
| 0
|
+| parentJoinChar | \*
| |
@@ -25241,8 +25637,8 @@ This module provides the APIs for for common functionality related to loading.
* [~parseManufacturerData(db, ctx)](#module_Loader API_ Loader APIs..parseManufacturerData) ⇒
* [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒
* [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒
- * [~parseFeatureConformance(operand)](#module_Loader API_ Loader APIs..parseFeatureConformance) ⇒
- * [~parseAndOrConformanceTerms(operand, joinChar)](#module_Loader API_ Loader APIs..parseAndOrConformanceTerms) ⇒
+ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒
+ * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒
* [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒
* [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒
* [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒
@@ -26593,10 +26989,14 @@ Key/velues of the object itself, end up in CODE/LABEL combinations.
| packageId | \*
|
| featureFlags | \*
|
-
+
+
+### Loader API: Loader APIs~parseConformanceFromXML(operand) ⇒
+Parses conformance from XML data.
+The conformance could come from features, attributes, commands, or events
-### Loader API: Loader APIs~parseFeatureConformance(operand) ⇒
-Parses feature conformance or an operand in feature conformance recursively from xml data.
+Call recursive helper function to parse conformance only if the conformance exists.
+Otherwise, return empty string directly
An example of parsing the conformance of 'User' device type feature:
@@ -26611,7 +27011,7 @@ Input operand from xml data:
{ "feature": [
{ "$": {"name": "PIN"}},
{ "$": {"name": "RID"}},
- { "$": {"name": "FPG"}},
+ { "$": {"name": "FGP"}},
{ "$": {"name": "FACE"}}
]
}
@@ -26622,28 +27022,32 @@ Input operand from xml data:
]
}
-Output device type feature conformance string:
- "Matter & (PIN | RID | FPG | FACE)"
+Output conformance string:
+ "Matter & (PIN | RID | FGP | FACE)"
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: The feature conformance string.
+**Returns**: The conformance string
-| Param | Type | Description |
-| --- | --- | --- |
-| operand | \*
| The operand to be parsed. |
+| Param | Type |
+| --- | --- |
+| operand | \*
|
+
+
-
+### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒
+helper function to parse conformance or an operand in conformance recursively
-### Loader API: Loader APIs~parseAndOrConformanceTerms(operand, joinChar) ⇒
-Helper function to parse andTerm or orTerm from xml data
+The baseLevelTerms variable include terms that can not have nested terms.
+When they appear, stop recursing and return the name inside directly
**Kind**: inner method of [Loader API: Loader APIs
](#module_Loader API_ Loader APIs)
-**Returns**: feature conformance string
+**Returns**: The conformance string.
-| Param | Type |
-| --- | --- |
-| operand | \*
|
-| joinChar | \*
|
+| Param | Type | Default |
+| --- | --- | --- |
+| operand | \*
| |
+| depth | \*
| 0
|
+| parentJoinChar | \*
| |
diff --git a/docs/zap-schema.svg b/docs/zap-schema.svg
index 390b1a43ad..6f796b61f6 100644
--- a/docs/zap-schema.svg
+++ b/docs/zap-schema.svg
@@ -1,3113 +1,3088 @@
-
-
-
+
+
SchemaCrawler_Diagram
-
-generated by
-SchemaCrawler 16.22.2
-generated on
-2024-10-28 19:22:42
-
+
+generated by
+SchemaCrawler 16.22.2
+ZAP schema, Copyright (c) 2020 Silicon Labs, released under Apache 2.0 license.
+
access_72bb1dc3
-
-ACCESS
-
-[table]
-ACCESS_ID
-
-INTEGER
-
-auto-incremented
-OPERATION_REF
-
-INTEGER
-ROLE_REF
-
-INTEGER
-ACCESS_MODIFIER_REF
-
-INTEGER
-
+
+
+ACCESS
+
+[table]
+ACCESS_ID
+
+INTEGER
+
+auto-incremented
+OPERATION_REF
+
+INTEGER
+ROLE_REF
+
+INTEGER
+ACCESS_MODIFIER_REF
+
+INTEGER
+
access_modifier_f63f3fb1
-
-ACCESS_MODIFIER
-
-[table]
-ACCESS_MODIFIER_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-
+
+
+ACCESS_MODIFIER
+
+[table]
+ACCESS_MODIFIER_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+
access_72bb1dc3:w->access_modifier_f63f3fb1:e
-
-
-
-
-
-
-
-SCHCRWLR_F63ECB52_72BAA964
+
+
+
+
+
+
+
operation_93359a6
-
-OPERATION
-
-[table]
-OPERATION_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-
+
+
+OPERATION
+
+[table]
+OPERATION_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+
access_72bb1dc3:w->operation_93359a6:e
-
-
-
-
-
-
-
-SCHCRWLR_0932E547_72BAA964
+
+
+
+
+
+
+
role_26ecd5
-
-ROLE
-
-[table]
-ROLE_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-LEVEL
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-
+
+
+ROLE
+
+[table]
+ROLE_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+LEVEL
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+
access_72bb1dc3:w->role_26ecd5:e
-
-
-
-
-
-
-
-SCHCRWLR_00267876_72BAA964
+
+
+
+
+
+
+
attribute_access_b017dce6
-
-ATTRIBUTE_ACCESS
-
-[table]
-ATTRIBUTE_REF
-
-INTEGER
-ACCESS_REF
-
-INTEGER
-
+
+
+ATTRIBUTE_ACCESS
+
+[table]
+ATTRIBUTE_REF
+
+INTEGER
+ACCESS_REF
+
+INTEGER
+
attribute_access_b017dce6:w->access_72bb1dc3:e
-
-
-
-
-
-
-
-SCHCRWLR_72BAA964_B0176887
+
+
+
+
+
+
+
attribute_a6e02edb
-
-ATTRIBUTE
-
-[table]
-ATTRIBUTE_ID
-
-INTEGER
-
-auto-incremented
-CLUSTER_REF
-
-INTEGER
-PACKAGE_REF
-
-INTEGER
-CODE
-
-INTEGER
-MANUFACTURER_CODE
-
-INTEGER
-NAME
-
-TEXT
-TYPE
-
-TEXT
-SIDE
-
-TEXT
-DEFINE
-
-TEXT
-MIN
-
-TEXT
-MAX
-
-TEXT
-MIN_LENGTH
-
-INTEGER
-MAX_LENGTH
-
-INTEGER
-REPORT_MIN_INTERVAL
-
-INTEGER
-REPORT_MAX_INTERVAL
-
-INTEGER
-REPORTABLE_CHANGE
-
-TEXT
-REPORTABLE_CHANGE_LENGTH
-
-INTEGER
-IS_WRITABLE
-
-INTEGER
-DEFAULT_VALUE
-
-TEXT
-IS_SCENE_REQUIRED
-
-INTEGER
-IS_OPTIONAL
-
-INTEGER
-REPORTING_POLICY
-
-TEXT
-STORAGE_POLICY
-
-TEXT
-IS_NULLABLE
-
-INTEGER
-ARRAY_TYPE
-
-TEXT
-MUST_USE_TIMED_WRITE
-
-INTEGER
-INTRODUCED_IN_REF
-
-INTEGER
-REMOVED_IN_REF
-
-INTEGER
-API_MATURITY
-
-TEXT
-IS_CHANGE_OMITTED
-
-INTEGER
-PERSISTENCE
-
-TEXT
-
+
+
+ATTRIBUTE
+
+[table]
+ATTRIBUTE_ID
+
+INTEGER
+
+auto-incremented
+CLUSTER_REF
+
+INTEGER
+PACKAGE_REF
+
+INTEGER
+CODE
+
+INTEGER
+MANUFACTURER_CODE
+
+INTEGER
+NAME
+
+TEXT
+TYPE
+
+TEXT
+SIDE
+
+TEXT
+DEFINE
+
+TEXT
+CONFORMANCE
+
+TEXT
+MIN
+
+TEXT
+MAX
+
+TEXT
+MIN_LENGTH
+
+INTEGER
+MAX_LENGTH
+
+INTEGER
+REPORT_MIN_INTERVAL
+
+INTEGER
+REPORT_MAX_INTERVAL
+
+INTEGER
+REPORTABLE_CHANGE
+
+TEXT
+REPORTABLE_CHANGE_LENGTH
+
+INTEGER
+IS_WRITABLE
+
+INTEGER
+DEFAULT_VALUE
+
+TEXT
+IS_SCENE_REQUIRED
+
+INTEGER
+IS_OPTIONAL
+
+INTEGER
+REPORTING_POLICY
+
+TEXT
+STORAGE_POLICY
+
+TEXT
+IS_NULLABLE
+
+INTEGER
+ARRAY_TYPE
+
+TEXT
+MUST_USE_TIMED_WRITE
+
+INTEGER
+INTRODUCED_IN_REF
+
+INTEGER
+REMOVED_IN_REF
+
+INTEGER
+API_MATURITY
+
+TEXT
+IS_CHANGE_OMITTED
+
+INTEGER
+PERSISTENCE
+
+TEXT
+MANUFACTURER_CODE_DERIVED
+
+generated
+
attribute_access_b017dce6:w->attribute_a6e02edb:e
-
-
-
-
-
-
-
-SCHCRWLR_A6DFBA7C_B0176887
+
+
+
+
+
+
+
cluster_access_38ea13c8
-
-CLUSTER_ACCESS
-
-[table]
-CLUSTER_REF
-
-INTEGER
-ACCESS_REF
-
-INTEGER
-
+
+
+CLUSTER_ACCESS
+
+[table]
+CLUSTER_REF
+
+INTEGER
+ACCESS_REF
+
+INTEGER
+
cluster_access_38ea13c8:w->access_72bb1dc3:e
-
-
-
-
-
-
-
-SCHCRWLR_72BAA964_38E99F69
+
+
+
+
+
+
+
cluster_5ec71239
-
-CLUSTER
-
-[table]
-CLUSTER_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-DOMAIN_NAME
-
-TEXT
-CODE
-
-INTEGER
-MANUFACTURER_CODE
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-DEFINE
-
-TEXT
-IS_SINGLETON
-
-INTEGER
-REVISION
-
-INTEGER
-INTRODUCED_IN_REF
-
-INTEGER
-REMOVED_IN_REF
-
-INTEGER
-API_MATURITY
-
-TEXT
-
+
+
+CLUSTER
+
+[table]
+CLUSTER_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+DOMAIN_NAME
+
+TEXT
+CODE
+
+INTEGER
+MANUFACTURER_CODE
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+DEFINE
+
+TEXT
+IS_SINGLETON
+
+INTEGER
+REVISION
+
+INTEGER
+INTRODUCED_IN_REF
+
+INTEGER
+REMOVED_IN_REF
+
+INTEGER
+API_MATURITY
+
+TEXT
+MANUFACTURER_CODE_DERIVED
+
+generated
+
cluster_access_38ea13c8:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_38E99F69
+
+
+
+
+
+
+
command_access_b02dd957
-
-COMMAND_ACCESS
-
-[table]
-COMMAND_REF
-
-INTEGER
-ACCESS_REF
-
-INTEGER
-
+
+
+COMMAND_ACCESS
+
+[table]
+COMMAND_REF
+
+INTEGER
+ACCESS_REF
+
+INTEGER
+
command_access_b02dd957:w->access_72bb1dc3:e
-
-
-
-
-
-
-
-SCHCRWLR_72BAA964_B02D64F8
+
+
+
+
+
+
+
command_6371df8a
-
-COMMAND
-
-[table]
-COMMAND_ID
-
-INTEGER
-
-auto-incremented
-CLUSTER_REF
-
-INTEGER
-PACKAGE_REF
-
-INTEGER
-CODE
-
-INTEGER
-MANUFACTURER_CODE
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-SOURCE
-
-TEXT
-IS_OPTIONAL
-
-INTEGER
-MUST_USE_TIMED_INVOKE
-
-INTEGER
-IS_FABRIC_SCOPED
-
-INTEGER
-INTRODUCED_IN_REF
-
-INTEGER
-REMOVED_IN_REF
-
-INTEGER
-RESPONSE_NAME
-
-INTEGER
-RESPONSE_REF
-
-INTEGER
-IS_DEFAULT_RESPONSE_ENABLED
-
-INTEGER
-IS_LARGE_MESSAGE
-
-INTEGER
-
+
+
+COMMAND
+
+[table]
+COMMAND_ID
+
+INTEGER
+
+auto-incremented
+CLUSTER_REF
+
+INTEGER
+PACKAGE_REF
+
+INTEGER
+CODE
+
+INTEGER
+MANUFACTURER_CODE
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+SOURCE
+
+TEXT
+IS_OPTIONAL
+
+INTEGER
+CONFORMANCE
+
+TEXT
+MUST_USE_TIMED_INVOKE
+
+INTEGER
+IS_FABRIC_SCOPED
+
+INTEGER
+INTRODUCED_IN_REF
+
+INTEGER
+REMOVED_IN_REF
+
+INTEGER
+RESPONSE_NAME
+
+INTEGER
+RESPONSE_REF
+
+INTEGER
+IS_DEFAULT_RESPONSE_ENABLED
+
+INTEGER
+IS_LARGE_MESSAGE
+
+INTEGER
+MANUFACTURER_CODE_DERIVED
+
+generated
+
command_access_b02dd957:w->command_6371df8a:e
-
-
-
-
-
-
-
-SCHCRWLR_63716B2B_B02D64F8
+
+
+
+
+
+
+
default_access_7ba041a1
-
-DEFAULT_ACCESS
-
-[table]
-PACKAGE_REF
-
-INTEGER
-ENTITY_TYPE
-
-TEXT
-ACCESS_REF
-
-INTEGER
-
+
+
+DEFAULT_ACCESS
+
+[table]
+PACKAGE_REF
+
+INTEGER
+ENTITY_TYPE
+
+TEXT
+ACCESS_REF
+
+INTEGER
+
default_access_7ba041a1:w->access_72bb1dc3:e
-
-
-
-
-
-
-
-SCHCRWLR_72BAA964_7B9FCD42
+
+
+
+
+
+
+
package_fab13485
-
-PACKAGE
-
-[table]
-PACKAGE_ID
-
-INTEGER
-
-auto-incremented
-PARENT_PACKAGE_REF
-
-INTEGER
-PATH
-
-TEXT NOT NULL
-TYPE
-
-TEXT
-CRC
-
-INTEGER
-VERSION
-
-INTEGER
-CATEGORY
-
-TEXT
-DESCRIPTION
-
-TEXT
-IS_IN_SYNC
-
-BOOLEAN
-
+
+
+PACKAGE
+
+[table]
+PACKAGE_ID
+
+INTEGER
+
+auto-incremented
+PARENT_PACKAGE_REF
+
+INTEGER
+PATH
+
+TEXT NOT NULL
+TYPE
+
+TEXT
+CRC
+
+INTEGER
+VERSION
+
+INTEGER
+CATEGORY
+
+TEXT
+DESCRIPTION
+
+TEXT
+IS_IN_SYNC
+
+BOOLEAN
+
default_access_7ba041a1:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_7B9FCD42
+
+
+
+
+
+
+
event_access_4668c328
-
-EVENT_ACCESS
-
-[table]
-EVENT_REF
-
-INTEGER
-ACCESS_REF
-
-INTEGER
-
+
+
+EVENT_ACCESS
+
+[table]
+EVENT_REF
+
+INTEGER
+ACCESS_REF
+
+INTEGER
+
event_access_4668c328:w->access_72bb1dc3:e
-
-
-
-
-
-
-
-SCHCRWLR_72BAA964_46684EC9
+
+
+
+
+
+
+
event_3f4eed9
-
-EVENT
-
-[table]
-EVENT_ID
-
-INTEGER
-
-auto-incremented
-CLUSTER_REF
-
-INTEGER
-PACKAGE_REF
-
-INTEGER
-CODE
-
-INTEGER
-MANUFACTURER_CODE
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-SIDE
-
-TEXT
-IS_OPTIONAL
-
-INTEGER
-IS_FABRIC_SENSITIVE
-
-INTEGER
-PRIORITY
-
-TEXT
-INTRODUCED_IN_REF
-
-INTEGER
-REMOVED_IN_REF
-
-INTEGER
-
+
+
+EVENT
+
+[table]
+EVENT_ID
+
+INTEGER
+
+auto-incremented
+CLUSTER_REF
+
+INTEGER
+PACKAGE_REF
+
+INTEGER
+CODE
+
+INTEGER
+MANUFACTURER_CODE
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+SIDE
+
+TEXT
+CONFORMANCE
+
+TEXT
+IS_OPTIONAL
+
+INTEGER
+IS_FABRIC_SENSITIVE
+
+INTEGER
+PRIORITY
+
+TEXT
+INTRODUCED_IN_REF
+
+INTEGER
+REMOVED_IN_REF
+
+INTEGER
+MANUFACTURER_CODE_DERIVED
+
+generated
+
event_access_4668c328:w->event_3f4eed9:e
-
-
-
-
-
-
-
-SCHCRWLR_03F47A7A_46684EC9
+
+
+
+
+
+
+
access_modifier_f63f3fb1:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_F63ECB52
+
+
+
+
+
+
+
atomic_73b03e8a
-
-"ATOMIC"
-
-[table]
-ATOMIC_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-ATOMIC_IDENTIFIER
-
-INTEGER
-ATOMIC_SIZE
-
-INTEGER
-IS_DISCRETE
-
-INTEGER
-IS_STRING
-
-INTEGER
-IS_LONG
-
-INTEGER
-IS_CHAR
-
-INTEGER
-IS_SIGNED
-
-INTEGER
-IS_COMPOSITE
-
-INTEGER
-IS_FLOAT
-
-INTEGER
-BASE_TYPE
-
-TEXT
-
+
+
+"ATOMIC"
+
+[table]
+ATOMIC_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+ATOMIC_IDENTIFIER
+
+INTEGER
+ATOMIC_SIZE
+
+INTEGER
+IS_DISCRETE
+
+INTEGER
+IS_STRING
+
+INTEGER
+IS_LONG
+
+INTEGER
+IS_CHAR
+
+INTEGER
+IS_SIGNED
+
+INTEGER
+IS_COMPOSITE
+
+INTEGER
+IS_FLOAT
+
+INTEGER
+BASE_TYPE
+
+TEXT
+
atomic_73b03e8a:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_CE3170F5
+
+
+
+
+
+
+
attribute_a6e02edb:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_A6DFBA7C
+
+
+
+
+
+
+
attribute_a6e02edb:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_A6DFBA7C
+
+
+
+
+
+
+
spec_27641a
-
-SPEC
-
-[table]
-SPEC_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-CODE
-
-TEXT NOT NULL
-DESCRIPTION
-
-TEXT
-CERTIFIABLE
-
-INTEGER
-
+
+
+SPEC
+
+[table]
+SPEC_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+CODE
+
+TEXT NOT NULL
+DESCRIPTION
+
+TEXT
+CERTIFIABLE
+
+INTEGER
+
attribute_a6e02edb:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_A6DFBA7C
+
+
+
+
+
+
+
attribute_a6e02edb:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_A6DFBA7C
+
+
+
+
+
+
+
device_type_attribute_ce5151f
-
-DEVICE_TYPE_ATTRIBUTE
-
-[table]
-DEVICE_TYPE_CLUSTER_REF
-
-INTEGER
-ATTRIBUTE_REF
-
-INTEGER
-ATTRIBUTE_NAME
-
-TEXT
-
+
+
+DEVICE_TYPE_ATTRIBUTE
+
+[table]
+DEVICE_TYPE_CLUSTER_REF
+
+INTEGER
+ATTRIBUTE_REF
+
+INTEGER
+ATTRIBUTE_NAME
+
+TEXT
+
device_type_attribute_ce5151f:w->attribute_a6e02edb:e
-
-
-
-
-
-
-
-SCHCRWLR_A6DFBA7C_0CE4A0C0
+
+
+
+
+
+
+
device_type_cluster_7298b97d
-
-DEVICE_TYPE_CLUSTER
-
-[table]
-DEVICE_TYPE_CLUSTER_ID
-
-INTEGER
-
-auto-incremented
-DEVICE_TYPE_REF
-
-INTEGER
-CLUSTER_REF
-
-INTEGER
-CLUSTER_NAME
-
-TEXT
-INCLUDE_CLIENT
-
-INTEGER
-INCLUDE_SERVER
-
-INTEGER
-LOCK_CLIENT
-
-INTEGER
-LOCK_SERVER
-
-INTEGER
-
+
+
+DEVICE_TYPE_CLUSTER
+
+[table]
+DEVICE_TYPE_CLUSTER_ID
+
+INTEGER
+
+auto-incremented
+DEVICE_TYPE_REF
+
+INTEGER
+CLUSTER_REF
+
+INTEGER
+CLUSTER_NAME
+
+TEXT
+INCLUDE_CLIENT
+
+INTEGER
+INCLUDE_SERVER
+
+INTEGER
+LOCK_CLIENT
+
+INTEGER
+LOCK_SERVER
+
+INTEGER
+
device_type_attribute_ce5151f:w->device_type_cluster_7298b97d:e
-
-
-
-
-
-
-
-SCHCRWLR_7298451E_0CE4A0C0
+
+
+
+
+
+
+
endpoint_type_attribute_c265400
-
-ENDPOINT_TYPE_ATTRIBUTE
-
-[table]
-ENDPOINT_TYPE_ATTRIBUTE_ID
-
-INTEGER
-
-auto-incremented
-ENDPOINT_TYPE_CLUSTER_REF
-
-INTEGER
-ATTRIBUTE_REF
-
-INTEGER
-INCLUDED
-
-INTEGER
-STORAGE_OPTION
-
-TEXT
-SINGLETON
-
-INTEGER
-BOUNDED
-
-INTEGER
-DEFAULT_VALUE
-
-TEXT
-INCLUDED_REPORTABLE
-
-INTEGER
-MIN_INTERVAL
-
-INTEGER
-MAX_INTERVAL
-
-INTEGER
-REPORTABLE_CHANGE
-
-INTEGER
-
+
+
+ENDPOINT_TYPE_ATTRIBUTE
+
+[table]
+ENDPOINT_TYPE_ATTRIBUTE_ID
+
+INTEGER
+
+auto-incremented
+ENDPOINT_TYPE_CLUSTER_REF
+
+INTEGER
+ATTRIBUTE_REF
+
+INTEGER
+INCLUDED
+
+INTEGER
+STORAGE_OPTION
+
+TEXT
+SINGLETON
+
+INTEGER
+BOUNDED
+
+INTEGER
+DEFAULT_VALUE
+
+TEXT
+INCLUDED_REPORTABLE
+
+INTEGER
+MIN_INTERVAL
+
+INTEGER
+MAX_INTERVAL
+
+INTEGER
+REPORTABLE_CHANGE
+
+INTEGER
+
endpoint_type_attribute_c265400:w->attribute_a6e02edb:e
-
-
-
-
-
-
-
-SCHCRWLR_A6DFBA7C_0C25DFA1
+
+
+
+
+
+
+
endpoint_type_cluster_c12e3c9e
-
-ENDPOINT_TYPE_CLUSTER
-
-[table]
-ENDPOINT_TYPE_CLUSTER_ID
-
-INTEGER
-
-auto-incremented
-ENDPOINT_TYPE_REF
-
-INTEGER
-CLUSTER_REF
-
-INTEGER
-SIDE
-
-TEXT
-ENABLED
-
-INTEGER
-
+
+
+ENDPOINT_TYPE_CLUSTER
+
+[table]
+ENDPOINT_TYPE_CLUSTER_ID
+
+INTEGER
+
+auto-incremented
+ENDPOINT_TYPE_REF
+
+INTEGER
+CLUSTER_REF
+
+INTEGER
+SIDE
+
+TEXT
+ENABLED
+
+INTEGER
+
endpoint_type_attribute_c265400:w->endpoint_type_cluster_c12e3c9e:e
-
-
-
-
-
-
-
-SCHCRWLR_C12DC83F_0C25DFA1
+
+
+
+
+
+
+
global_attribute_default_73c65a21
-
-GLOBAL_ATTRIBUTE_DEFAULT
-
-[table]
-GLOBAL_ATTRIBUTE_DEFAULT_ID
-
-INTEGER
-
-auto-incremented
-CLUSTER_REF
-
-INTEGER NOT NULL
-ATTRIBUTE_REF
-
-INTEGER NOT NULL
-DEFAULT_VALUE
-
-TEXT
-
+
+
+GLOBAL_ATTRIBUTE_DEFAULT
+
+[table]
+GLOBAL_ATTRIBUTE_DEFAULT_ID
+
+INTEGER
+
+auto-incremented
+CLUSTER_REF
+
+INTEGER NOT NULL
+ATTRIBUTE_REF
+
+INTEGER NOT NULL
+DEFAULT_VALUE
+
+TEXT
+
global_attribute_default_73c65a21:w->attribute_a6e02edb:e
-
-
-
-
-
-
-
-SCHCRWLR_A6DFBA7C_73C5E5C2
+
+
+
+
+
+
+
global_attribute_default_73c65a21:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_73C5E5C2
+
+
+
+
+
+
+
attribute_mapping_caf33e4a
-
-ATTRIBUTE_MAPPING
-
-[table]
-ATTRIBUTE_MAPPING_ID
-
-INTEGER
-
-auto-incremented
-ATTRIBUTE_LEFT_REF
-
-INTEGER
-ATTRIBUTE_RIGHT_REF
-
-INTEGER
-
+
+
+ATTRIBUTE_MAPPING
+
+[table]
+ATTRIBUTE_MAPPING_ID
+
+INTEGER
+
+auto-incremented
+ATTRIBUTE_LEFT_REF
+
+INTEGER
+ATTRIBUTE_RIGHT_REF
+
+INTEGER
+
attribute_mapping_caf33e4a:w->attribute_a6e02edb:e
-
-
-
-
-
-
-
-
-SCHCRWLR_A6DFBA7C_CAF2C9EB
+
+
+
+
+
+
+
+
attribute_mapping_caf33e4a:w->attribute_a6e02edb:e
-
-
-
-
-
-
-
-
-SCHCRWLR_A6DFBA7C_CAF2C9EB
+
+
+
+
+
+
+
+
bitmap_74cc598e
-
-BITMAP
-
-[table]
-BITMAP_ID
-
-INTEGER NOT NULL
-SIZE
-
-INTEGER
-
+
+
+BITMAP
+
+[table]
+BITMAP_ID
+
+INTEGER NOT NULL
+SIZE
+
+INTEGER
+
data_type_9233070e
-
-DATA_TYPE
-
-[table]
-DATA_TYPE_ID
-
-INTEGER NOT NULL
-
-auto-incremented
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-DISCRIMINATOR_REF
-
-INTEGER
-PACKAGE_REF
-
-INTEGER
-
+
+
+DATA_TYPE
+
+[table]
+DATA_TYPE_ID
+
+INTEGER NOT NULL
+
+auto-incremented
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+DISCRIMINATOR_REF
+
+INTEGER
+PACKAGE_REF
+
+INTEGER
+
bitmap_74cc598e:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_74CBE52F
+
+
+
+
+
+
+
bitmap_field_bfea8629
-
-BITMAP_FIELD
-
-[table]
-BITMAP_FIELD_ID
-
-INTEGER NOT NULL
-
-auto-incremented
-BITMAP_REF
-
-INTEGER
-FIELD_IDENTIFIER
-
-INTEGER
-NAME
-
-TEXT(100)
-MASK
-
-INTEGER
-TYPE
-
-TEXT(100)
-
+
+
+BITMAP_FIELD
+
+[table]
+BITMAP_FIELD_ID
+
+INTEGER NOT NULL
+
+auto-incremented
+BITMAP_REF
+
+INTEGER
+FIELD_IDENTIFIER
+
+INTEGER
+NAME
+
+TEXT(100)
+MASK
+
+INTEGER
+TYPE
+
+TEXT(100)
+
bitmap_field_bfea8629:w->bitmap_74cc598e:e
-
-
-
-
-
-
-
-SCHCRWLR_74CBE52F_BFEA11CA
+
+
+
+
+
+
+
cluster_5ec71239:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_5EC69DDA
+
+
+
+
+
+
+
cluster_5ec71239:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_5EC69DDA
+
+
+
+
+
+
+
cluster_5ec71239:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_5EC69DDA
+
+
+
+
+
+
+
command_6371df8a:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_63716B2B
+
+
+
+
+
+
+
command_6371df8a:w->command_6371df8a:e
-
-
-
-
-
-
-
-SCHCRWLR_63716B2B_63716B2B
+
+
+
+
+
+
+
command_6371df8a:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_63716B2B
+
+
+
+
+
+
+
command_6371df8a:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_63716B2B
+
+
+
+
+
+
+
command_6371df8a:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_63716B2B
+
+
+
+
+
+
+
data_type_cluster_8d9f2ca9
-
-DATA_TYPE_CLUSTER
-
-[table]
-DATA_TYPE_CLUSTER_ID
-
-INTEGER NOT NULL
-
-auto-incremented
-CLUSTER_REF
-
-INTEGER
-CLUSTER_CODE
-
-INTEGER
-DATA_TYPE_REF
-
-INTEGER
-
+
+
+DATA_TYPE_CLUSTER
+
+[table]
+DATA_TYPE_CLUSTER_ID
+
+INTEGER NOT NULL
+
+auto-incremented
+CLUSTER_REF
+
+INTEGER
+CLUSTER_CODE
+
+INTEGER
+DATA_TYPE_REF
+
+INTEGER
+
data_type_cluster_8d9f2ca9:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_8D9EB84A
+
+
+
+
+
+
+
data_type_cluster_8d9f2ca9:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_8D9EB84A
+
+
+
+
+
+
+
device_type_cluster_7298b97d:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_7298451E
+
+
+
+
+
+
+
device_type_2620a7e2
-
-DEVICE_TYPE
-
-[table]
-DEVICE_TYPE_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-DOMAIN
-
-TEXT
-CODE
-
-INTEGER
-PROFILE_ID
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-CLASS
-
-TEXT
-"SCOPE"
-
-TEXT
-SUPERSET
-
-TEXT
-
+
+
+DEVICE_TYPE
+
+[table]
+DEVICE_TYPE_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+DOMAIN
+
+TEXT
+CODE
+
+INTEGER
+PROFILE_ID
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+CLASS
+
+TEXT
+"SCOPE"
+
+TEXT
+SUPERSET
+
+TEXT
+
device_type_cluster_7298b97d:w->device_type_2620a7e2:e
-
-
-
-
-
-
-
-SCHCRWLR_26203383_7298451E
+
+
+
+
+
+
+
endpoint_type_cluster_c12e3c9e:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_C12DC83F
+
+
+
+
+
+
+
endpoint_type_9857dc03
-
-ENDPOINT_TYPE
-
-[table]
-ENDPOINT_TYPE_ID
-
-INTEGER
-
-auto-incremented
-SESSION_PARTITION_REF
-
-INTEGER
-NAME
-
-TEXT
-
+
+
+ENDPOINT_TYPE
+
+[table]
+ENDPOINT_TYPE_ID
+
+INTEGER
+
+auto-incremented
+SESSION_PARTITION_REF
+
+INTEGER
+NAME
+
+TEXT
+
endpoint_type_cluster_c12e3c9e:w->endpoint_type_9857dc03:e
-
-
-
-
-
-
-
-SCHCRWLR_985767A4_C12DC83F
+
+
+
+
+
+
+
event_3f4eed9:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_03F47A7A
+
+
+
+
+
+
+
event_3f4eed9:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_03F47A7A
+
+
+
+
+
+
+
event_3f4eed9:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_03F47A7A
+
+
+
+
+
+
+
event_3f4eed9:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_03F47A7A
+
+
+
+
+
+
+
feature_f06e7b35
-
-FEATURE
-
-[table]
-FEATURE_ID
-
-INTEGER
-
-auto-incremented
-NAME
-
-TEXT
-CODE
-
-TEXT
-BIT
-
-INTEGER
-DEFAULT_VALUE
-
-INTEGER
-DESCRIPTION
-
-TEXT
-CONFORMANCE
-
-TEXT
-PACKAGE_REF
-
-INTEGER
-CLUSTER_REF
-
-INTEGER
-
+
+
+FEATURE
+
+[table]
+FEATURE_ID
+
+INTEGER
+
+auto-incremented
+NAME
+
+TEXT
+CODE
+
+TEXT
+BIT
+
+INTEGER
+DEFAULT_VALUE
+
+INTEGER
+DESCRIPTION
+
+TEXT
+CONFORMANCE
+
+TEXT
+PACKAGE_REF
+
+INTEGER
+CLUSTER_REF
+
+INTEGER
+
feature_f06e7b35:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_F06E06D6
+
+
+
+
+
+
+
feature_f06e7b35:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_F06E06D6
+
+
+
+
+
+
+
tag_1b7d9
-
-TAG
-
-[table]
-TAG_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-CLUSTER_REF
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-
+
+
+TAG
+
+[table]
+TAG_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+CLUSTER_REF
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+
tag_1b7d9:w->cluster_5ec71239:e
-
-
-
-
-
-
-
-SCHCRWLR_5EC69DDA_0001437A
+
+
+
+
+
+
+
tag_1b7d9:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_0001437A
+
+
+
+
+
+
+
command_arg_294e7f81
-
-COMMAND_ARG
-
-[table]
-COMMAND_REF
-
-INTEGER
-FIELD_IDENTIFIER
-
-INTEGER
-NAME
-
-TEXT
-TYPE
-
-TEXT
-MIN
-
-TEXT
-MAX
-
-TEXT
-MIN_LENGTH
-
-INTEGER
-MAX_LENGTH
-
-INTEGER
-IS_ARRAY
-
-INTEGER
-PRESENT_IF
-
-TEXT
-IS_NULLABLE
-
-INTEGER
-IS_OPTIONAL
-
-INTEGER
-COUNT_ARG
-
-TEXT
-INTRODUCED_IN_REF
-
-INTEGER
-REMOVED_IN_REF
-
-INTEGER
-
+
+
+COMMAND_ARG
+
+[table]
+COMMAND_REF
+
+INTEGER
+FIELD_IDENTIFIER
+
+INTEGER
+NAME
+
+TEXT
+TYPE
+
+TEXT
+MIN
+
+TEXT
+MAX
+
+TEXT
+MIN_LENGTH
+
+INTEGER
+MAX_LENGTH
+
+INTEGER
+IS_ARRAY
+
+INTEGER
+PRESENT_IF
+
+TEXT
+IS_NULLABLE
+
+INTEGER
+IS_OPTIONAL
+
+INTEGER
+COUNT_ARG
+
+TEXT
+INTRODUCED_IN_REF
+
+INTEGER
+REMOVED_IN_REF
+
+INTEGER
+
command_arg_294e7f81:w->command_6371df8a:e
-
-
-
-
-
-
-
-SCHCRWLR_63716B2B_294E0B22
+
+
+
+
+
+
+
command_arg_294e7f81:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_294E0B22
+
+
+
+
+
+
+
command_arg_294e7f81:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_294E0B22
+
+
+
+
+
+
+
device_type_command_774386ce
-
-DEVICE_TYPE_COMMAND
-
-[table]
-DEVICE_TYPE_CLUSTER_REF
-
-INTEGER
-COMMAND_REF
-
-INTEGER
-COMMAND_NAME
-
-TEXT
-
+
+
+DEVICE_TYPE_COMMAND
+
+[table]
+DEVICE_TYPE_CLUSTER_REF
+
+INTEGER
+COMMAND_REF
+
+INTEGER
+COMMAND_NAME
+
+TEXT
+
device_type_command_774386ce:w->command_6371df8a:e
-
-
-
-
-
-
-
-SCHCRWLR_63716B2B_7743126F
+
+
+
+
+
+
+
device_type_command_774386ce:w->device_type_cluster_7298b97d:e
-
-
-
-
-
-
-
-SCHCRWLR_7298451E_7743126F
+
+
+
+
+
+
+
endpoint_type_command_c5d909ef
-
-ENDPOINT_TYPE_COMMAND
-
-[table]
-ENDPOINT_TYPE_COMMAND_ID
-
-INTEGER
-
-auto-incremented
-ENDPOINT_TYPE_CLUSTER_REF
-
-INTEGER
-COMMAND_REF
-
-INTEGER
-IS_INCOMING
-
-INTEGER
-IS_ENABLED
-
-INTEGER
-
+
+
+ENDPOINT_TYPE_COMMAND
+
+[table]
+ENDPOINT_TYPE_COMMAND_ID
+
+INTEGER
+
+auto-incremented
+ENDPOINT_TYPE_CLUSTER_REF
+
+INTEGER
+COMMAND_REF
+
+INTEGER
+IS_INCOMING
+
+INTEGER
+IS_ENABLED
+
+INTEGER
+
endpoint_type_command_c5d909ef:w->command_6371df8a:e
-
-
-
-
-
-
-
-SCHCRWLR_63716B2B_C5D89590
+
+
+
+
+
+
+
endpoint_type_command_c5d909ef:w->endpoint_type_cluster_c12e3c9e:e
-
-
-
-
-
-
-
-SCHCRWLR_C12DC83F_C5D89590
+
+
+
+
+
+
+
discriminator_4931d2db
-
-DISCRIMINATOR
-
-[table]
-DISCRIMINATOR_ID
-
-INTEGER NOT NULL
-
-auto-incremented
-NAME
-
-TEXT
-PACKAGE_REF
-
-INTEGER
-
+
+
+DISCRIMINATOR
+
+[table]
+DISCRIMINATOR_ID
+
+INTEGER NOT NULL
+
+auto-incremented
+NAME
+
+TEXT
+PACKAGE_REF
+
+INTEGER
+
data_type_9233070e:w->discriminator_4931d2db:e
-
-
-
-
-
-
-
-SCHCRWLR_49315E7C_923292AF
+
+
+
+
+
+
+
data_type_9233070e:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_923292AF
+
+
+
+
+
+
+
enum_210160
-
-ENUM
-
-[table]
-ENUM_ID
-
-INTEGER NOT NULL
-SIZE
-
-INTEGER
-
+
+
+ENUM
+
+[table]
+ENUM_ID
+
+INTEGER NOT NULL
+SIZE
+
+INTEGER
+
enum_210160:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_00208D01
+
+
+
+
+
+
+
number_89ec43a8
-
-NUMBER
-
-[table]
-NUMBER_ID
-
-INTEGER NOT NULL
-SIZE
-
-INTEGER
-IS_SIGNED
-
-INTEGER
-
+
+
+NUMBER
+
+[table]
+NUMBER_ID
+
+INTEGER NOT NULL
+SIZE
+
+INTEGER
+IS_SIGNED
+
+INTEGER
+
number_89ec43a8:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_89EBCF49
+
+
+
+
+
+
+
string_9268c870
-
-STRING
-
-[table]
-STRING_ID
-
-INTEGER NOT NULL
-IS_LONG
-
-INTEGER
-SIZE
-
-INTEGER
-IS_CHAR
-
-INTEGER
-
+
+
+STRING
+
+[table]
+STRING_ID
+
+INTEGER NOT NULL
+IS_LONG
+
+INTEGER
+SIZE
+
+INTEGER
+IS_CHAR
+
+INTEGER
+
string_9268c870:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_92685411
+
+
+
+
+
+
+
struct_9268f434
-
-STRUCT
-
-[table]
-STRUCT_ID
-
-INTEGER NOT NULL
-IS_FABRIC_SCOPED
-
-INTEGER
-SIZE
-
-INTEGER
-API_MATURITY
-
-TEXT
-
+
+
+STRUCT
+
+[table]
+STRUCT_ID
+
+INTEGER NOT NULL
+IS_FABRIC_SCOPED
+
+INTEGER
+SIZE
+
+INTEGER
+API_MATURITY
+
+TEXT
+
struct_9268f434:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_92687FD5
+
+
+
+
+
+
+
struct_item_d6e4bd9c
-
-STRUCT_ITEM
-
-[table]
-STRUCT_ITEM_ID
-
-INTEGER NOT NULL
-
-auto-incremented
-STRUCT_REF
-
-INTEGER
-FIELD_IDENTIFIER
-
-INTEGER
-NAME
-
-TEXT(100)
-IS_ARRAY
-
-INTEGER
-IS_ENUM
-
-INTEGER
-MIN_LENGTH
-
-INTEGER
-MAX_LENGTH
-
-INTEGER
-IS_WRITABLE
-
-INTEGER
-IS_NULLABLE
-
-INTEGER
-IS_OPTIONAL
-
-INTEGER
-IS_FABRIC_SENSITIVE
-
-INTEGER
-SIZE
-
-INTEGER
-DATA_TYPE_REF
-
-INTEGER NOT NULL
-
+
+
+STRUCT_ITEM
+
+[table]
+STRUCT_ITEM_ID
+
+INTEGER NOT NULL
+
+auto-incremented
+STRUCT_REF
+
+INTEGER
+FIELD_IDENTIFIER
+
+INTEGER
+NAME
+
+TEXT(100)
+IS_ARRAY
+
+INTEGER
+IS_ENUM
+
+INTEGER
+MIN_LENGTH
+
+INTEGER
+MAX_LENGTH
+
+INTEGER
+IS_WRITABLE
+
+INTEGER
+IS_NULLABLE
+
+INTEGER
+IS_OPTIONAL
+
+INTEGER
+IS_FABRIC_SENSITIVE
+
+INTEGER
+SIZE
+
+INTEGER
+DATA_TYPE_REF
+
+INTEGER NOT NULL
+
struct_item_d6e4bd9c:w->data_type_9233070e:e
-
-
-
-
-
-
-
-SCHCRWLR_923292AF_D6E4493D
+
+
+
+
+
+
+
struct_item_d6e4bd9c:w->struct_9268f434:e
-
-
-
-
-
-
-
-SCHCRWLR_92687FD5_D6E4493D
+
+
+
+
+
+
+
device_composition_eab6b180
-
-DEVICE_COMPOSITION
-
-[table]
-DEVICE_COMPOSITION_ID
-
-INTEGER
-
-auto-incremented
-CODE
-
-INTEGER
-DEVICE_TYPE_REF
-
-INTEGER
-ENDPOINT_COMPOSITION_REF
-
-INTEGER
-CONFORMANCE
-
-TEXT
-DEVICE_CONSTRAINT
-
-INTEGER
-
+
+
+DEVICE_COMPOSITION
+
+[table]
+DEVICE_COMPOSITION_ID
+
+INTEGER
+
+auto-incremented
+CODE
+
+INTEGER
+DEVICE_TYPE_REF
+
+INTEGER
+ENDPOINT_COMPOSITION_REF
+
+INTEGER
+CONFORMANCE
+
+TEXT
+DEVICE_CONSTRAINT
+
+INTEGER
+
device_composition_eab6b180:w->device_type_2620a7e2:e
-
-
-
-
-
-
-
-SCHCRWLR_26203383_EAB63D21
+
+
+
+
+
+
+
endpoint_composition_fdc3c63f
-
-ENDPOINT_COMPOSITION
-
-[table]
-ENDPOINT_COMPOSITION_ID
-
-INTEGER
-
-auto-incremented
-DEVICE_TYPE_REF
-
-INTEGER
-TYPE
-
-TEXT
-CODE
-
-INTEGER
-
+
+
+ENDPOINT_COMPOSITION
+
+[table]
+ENDPOINT_COMPOSITION_ID
+
+INTEGER
+
+auto-incremented
+DEVICE_TYPE_REF
+
+INTEGER
+TYPE
+
+TEXT
+CODE
+
+INTEGER
+
device_composition_eab6b180:w->endpoint_composition_fdc3c63f:e
-
-
-
-
-
-
-
-SCHCRWLR_FDC351E0_EAB63D21
+
+
+
+
+
+
+
device_type_2620a7e2:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_26203383
+
+
+
+
+
+
+
endpoint_composition_fdc3c63f:w->device_type_2620a7e2:e
-
-
-
-
-
-
-
-SCHCRWLR_26203383_FDC351E0
+
+
+
+
+
+
+
endpoint_type_device_e685fbb0
-
-ENDPOINT_TYPE_DEVICE
-
-[table]
-ENDPOINT_TYPE_DEVICE_ID
-
-INTEGER
-
-auto-incremented
-DEVICE_TYPE_REF
-
-INTEGER
-ENDPOINT_TYPE_REF
-
-INTEGER
-DEVICE_TYPE_ORDER
-
-INTEGER
-DEVICE_IDENTIFIER
-
-INTEGER
-DEVICE_VERSION
-
-INTEGER
-
+
+
+ENDPOINT_TYPE_DEVICE
+
+[table]
+ENDPOINT_TYPE_DEVICE_ID
+
+INTEGER
+
+auto-incremented
+DEVICE_TYPE_REF
+
+INTEGER
+ENDPOINT_TYPE_REF
+
+INTEGER
+DEVICE_TYPE_ORDER
+
+INTEGER
+DEVICE_IDENTIFIER
+
+INTEGER
+DEVICE_VERSION
+
+INTEGER
+
endpoint_type_device_e685fbb0:w->device_type_2620a7e2:e
-
-
-
-
-
-
-
-SCHCRWLR_26203383_E6858751
+
+
+
+
+
+
+
endpoint_type_device_e685fbb0:w->endpoint_type_9857dc03:e
-
-
-
-
-
-
-
-SCHCRWLR_985767A4_E6858751
+
+
+
+
+
+
+
device_type_feature_4402279
-
-DEVICE_TYPE_FEATURE
-
-[table]
-DEVICE_TYPE_CLUSTER_REF
-
-INTEGER
-FEATURE_REF
-
-INTEGER
-FEATURE_CODE
-
-TEXT
-DEVICE_TYPE_CLUSTER_CONFORMANCE
-
-TEXT
-
+
+
+DEVICE_TYPE_FEATURE
+
+[table]
+DEVICE_TYPE_CLUSTER_REF
+
+INTEGER
+FEATURE_REF
+
+INTEGER
+FEATURE_CODE
+
+TEXT
+DEVICE_TYPE_CLUSTER_CONFORMANCE
+
+TEXT
+
device_type_feature_4402279:w->device_type_cluster_7298b97d:e
-
-
-
-
-
-
-
-SCHCRWLR_7298451E_043FAE1A
+
+
+
+
+
+
+
device_type_feature_4402279:w->feature_f06e7b35:e
-
-
-
-
-
-
-
-SCHCRWLR_F06E06D6_043FAE1A
+
+
+
+
+
+
+
discriminator_4931d2db:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_49315E7C
+
+
+
+
+
+
+
domain_78873d23
-
-DOMAIN
-
-[table]
-DOMAIN_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-NAME
-
-TEXT
-LATEST_SPEC_REF
-
-INTEGER
-
+
+
+DOMAIN
+
+[table]
+DOMAIN_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+NAME
+
+TEXT
+LATEST_SPEC_REF
+
+INTEGER
+
domain_78873d23:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_7886C8C4
+
+
+
+
+
+
+
domain_78873d23:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_7886C8C4
+
+
+
+
+
+
+
endpoint_966d81f4
-
-ENDPOINT
-
-[table]
-ENDPOINT_ID
-
-INTEGER
-
-auto-incremented
-SESSION_REF
-
-INTEGER
-ENDPOINT_TYPE_REF
-
-INTEGER
-PROFILE
-
-INTEGER
-ENDPOINT_IDENTIFIER
-
-INTEGER
-NETWORK_IDENTIFIER
-
-INTEGER
-PARENT_ENDPOINT_REF
-
-INTEGER
-
+
+
+ENDPOINT
+
+[table]
+ENDPOINT_ID
+
+INTEGER
+
+auto-incremented
+SESSION_REF
+
+INTEGER
+ENDPOINT_TYPE_REF
+
+INTEGER
+PROFILE
+
+INTEGER
+ENDPOINT_IDENTIFIER
+
+INTEGER
+NETWORK_IDENTIFIER
+
+INTEGER
+PARENT_ENDPOINT_REF
+
+INTEGER
+
endpoint_966d81f4:w->endpoint_966d81f4:e
-
-
-
-
-
-
-
-SCHCRWLR_966D0D95_966D0D95
+
+
+
+
+
+
+
endpoint_966d81f4:w->endpoint_type_9857dc03:e
-
-
-
-
-
-
-
-SCHCRWLR_985767A4_966D0D95
+
+
+
+
+
+
+
session_a11c82d5
-
-SESSION
-
-[table]
-SESSION_ID
-
-INTEGER
-
-auto-incremented
-USER_REF
-
-INTEGER
-SESSION_KEY
-
-TEXT
-CREATION_TIME
-
-INTEGER
-DIRTY
-
-INTEGER
-NEW_NOTIFICATION
-
-INTEGER
-
+
+
+SESSION
+
+[table]
+SESSION_ID
+
+INTEGER
+
+auto-incremented
+USER_REF
+
+INTEGER
+SESSION_KEY
+
+TEXT
+CREATION_TIME
+
+INTEGER
+DIRTY
+
+INTEGER
+NEW_NOTIFICATION
+
+INTEGER
+
endpoint_966d81f4:w->session_a11c82d5:e
-
-
-
-
-
-
-
-SCHCRWLR_A11C0E76_966D0D95
+
+
+
+
+
+
+
session_partition_f35f84a0
-
-SESSION_PARTITION
-
-[table]
-SESSION_PARTITION_ID
-
-INTEGER
-
-auto-incremented
-SESSION_PARTITION_NUMBER
-
-INTEGER
-SESSION_REF
-
-INTEGER
-
+
+
+SESSION_PARTITION
+
+[table]
+SESSION_PARTITION_ID
+
+INTEGER
+
+auto-incremented
+SESSION_PARTITION_NUMBER
+
+INTEGER
+SESSION_REF
+
+INTEGER
+
endpoint_type_9857dc03:w->session_partition_f35f84a0:e
-
-
-
-
-
-
-
-SCHCRWLR_F35F1041_985767A4
+
+
+
+
+
+
+
endpoint_type_event_e67d6e7e
-
-ENDPOINT_TYPE_EVENT
-
-[table]
-ENDPOINT_TYPE_EVENT_ID
-
-INTEGER
-
-auto-incremented
-ENDPOINT_TYPE_CLUSTER_REF
-
-INTEGER
-EVENT_REF
-
-INTEGER
-INCLUDED
-
-INTEGER
-
+
+
+ENDPOINT_TYPE_EVENT
+
+[table]
+ENDPOINT_TYPE_EVENT_ID
+
+INTEGER
+
+auto-incremented
+ENDPOINT_TYPE_CLUSTER_REF
+
+INTEGER
+EVENT_REF
+
+INTEGER
+INCLUDED
+
+INTEGER
+
endpoint_type_event_e67d6e7e:w->endpoint_type_cluster_c12e3c9e:e
-
-
-
-
-
-
-
-SCHCRWLR_C12DC83F_E67CFA1F
+
+
+
+
+
+
+
endpoint_type_event_e67d6e7e:w->event_3f4eed9:e
-
-
-
-
-
-
-
-SCHCRWLR_03F47A7A_E67CFA1F
+
+
+
+
+
+
+
enum_item_b6420bf0
-
-ENUM_ITEM
-
-[table]
-ENUM_ITEM_ID
-
-INTEGER NOT NULL
-
-auto-incremented
-ENUM_REF
-
-INTEGER
-NAME
-
-TEXT
-DESCRIPTION
-
-TEXT
-FIELD_IDENTIFIER
-
-INTEGER
-"VALUE"
-
-INTEGER
-
+
+
+ENUM_ITEM
+
+[table]
+ENUM_ITEM_ID
+
+INTEGER NOT NULL
+
+auto-incremented
+ENUM_REF
+
+INTEGER
+NAME
+
+TEXT
+DESCRIPTION
+
+TEXT
+FIELD_IDENTIFIER
+
+INTEGER
+"VALUE"
+
+INTEGER
+
enum_item_b6420bf0:w->enum_210160:e
-
-
-
-
-
-
-
-SCHCRWLR_00208D01_B6419791
+
+
+
+
+
+
+
event_field_d102b734
-
-EVENT_FIELD
-
-[table]
-EVENT_REF
-
-INTEGER
-FIELD_IDENTIFIER
-
-INTEGER
-NAME
-
-TEXT
-TYPE
-
-TEXT
-IS_ARRAY
-
-INTEGER
-IS_NULLABLE
-
-INTEGER
-IS_OPTIONAL
-
-INTEGER
-INTRODUCED_IN_REF
-
-INTEGER
-REMOVED_IN_REF
-
-INTEGER
-
+
+
+EVENT_FIELD
+
+[table]
+EVENT_REF
+
+INTEGER
+FIELD_IDENTIFIER
+
+INTEGER
+NAME
+
+TEXT
+TYPE
+
+TEXT
+IS_ARRAY
+
+INTEGER
+IS_NULLABLE
+
+INTEGER
+IS_OPTIONAL
+
+INTEGER
+INTRODUCED_IN_REF
+
+INTEGER
+REMOVED_IN_REF
+
+INTEGER
+
event_field_d102b734:w->event_3f4eed9:e
-
-
-
-
-
-
-
-SCHCRWLR_03F47A7A_D10242D5
+
+
+
+
+
+
+
event_field_d102b734:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_D10242D5
+
+
+
+
+
+
+
event_field_d102b734:w->spec_27641a:e
-
-
-
-
-
-
-
-SCHCRWLR_0026EFBB_D10242D5
+
+
+
+
+
+
+
global_attribute_bit_e934f16d
-
-GLOBAL_ATTRIBUTE_BIT
-
-[table]
-GLOBAL_ATTRIBUTE_DEFAULT_REF
-
-INTEGER NOT NULL
-BIT
-
-INTEGER NOT NULL
-"VALUE"
-
-INTEGER
-TAG_REF
-
-INTEGER NOT NULL
-
+
+
+GLOBAL_ATTRIBUTE_BIT
+
+[table]
+GLOBAL_ATTRIBUTE_DEFAULT_REF
+
+INTEGER NOT NULL
+BIT
+
+INTEGER NOT NULL
+"VALUE"
+
+INTEGER
+TAG_REF
+
+INTEGER NOT NULL
+
global_attribute_bit_e934f16d:w->global_attribute_default_73c65a21:e
-
-
-
-
-
-
-
-SCHCRWLR_73C5E5C2_E9347D0E
+
+
+
+
+
+
+
global_attribute_bit_e934f16d:w->tag_1b7d9:e
-
-
-
-
-
-
-
-SCHCRWLR_0001437A_E9347D0E
+
+
+
+
+
+
+
operation_93359a6:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_0932E547
+
+
+
+
+
+
+
package_fab13485:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_FAB0C026
+
+
+
+
+
+
+
package_extension_2789e3a5
-
-PACKAGE_EXTENSION
-
-[table]
-PACKAGE_EXTENSION_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-ENTITY
-
-TEXT
-PROPERTY
-
-TEXT
-TYPE
-
-TEXT
-CONFIGURABILITY
-
-TEXT
-LABEL
-
-TEXT
-GLOBAL_DEFAULT
-
-TEXT
-
+
+
+PACKAGE_EXTENSION
+
+[table]
+PACKAGE_EXTENSION_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+ENTITY
+
+TEXT
+PROPERTY
+
+TEXT
+TYPE
+
+TEXT
+CONFIGURABILITY
+
+TEXT
+LABEL
+
+TEXT
+GLOBAL_DEFAULT
+
+TEXT
+
package_extension_2789e3a5:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_27896F46
+
+
+
+
+
+
+
package_notice_176ee570
-
-PACKAGE_NOTICE
-
-[table]
-PACKAGE_REF
-
-INTEGER
-NOTICE_TYPE
-
-TEXT
-NOTICE_MESSAGE
-
-TEXT
-NOTICE_SEVERITY
-
-INTEGER
-NOTICE_ID
-
-INTEGER
-
-auto-incremented
-
+
+
+PACKAGE_NOTICE
+
+[table]
+PACKAGE_REF
+
+INTEGER
+NOTICE_TYPE
+
+TEXT
+NOTICE_MESSAGE
+
+TEXT
+NOTICE_SEVERITY
+
+INTEGER
+NOTICE_ID
+
+INTEGER
+
+auto-incremented
+
package_notice_176ee570:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_176E7111
+
+
+
+
+
+
+
package_option_1931d70d
-
-PACKAGE_OPTION
-
-[table]
-OPTION_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-OPTION_CATEGORY
-
-TEXT
-OPTION_CODE
-
-TEXT
-OPTION_LABEL
-
-TEXT
-
+
+
+PACKAGE_OPTION
+
+[table]
+OPTION_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+OPTION_CATEGORY
+
+TEXT
+OPTION_CODE
+
+TEXT
+OPTION_LABEL
+
+TEXT
+
package_option_1931d70d:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_193162AE
+
+
+
+
+
+
+
package_option_default_64a251ef
-
-PACKAGE_OPTION_DEFAULT
-
-[table]
-OPTION_DEFAULT_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_REF
-
-INTEGER
-OPTION_CATEGORY
-
-TEXT
-OPTION_REF
-
-INTEGER
-
+
+
+PACKAGE_OPTION_DEFAULT
+
+[table]
+OPTION_DEFAULT_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_REF
+
+INTEGER
+OPTION_CATEGORY
+
+TEXT
+OPTION_REF
+
+INTEGER
+
package_option_default_64a251ef:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_64A1DD90
+
+
+
+
+
+
+
package_option_default_64a251ef:w->package_option_1931d70d:e
-
-
-
-
-
-
-
-SCHCRWLR_193162AE_64A1DD90
+
+
+
+
+
+
+
role_26ecd5:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_00267876
+
+
+
+
+
+
+
session_package_61fa13bc
-
-SESSION_PACKAGE
-
-[table]
-SESSION_PARTITION_REF
-
-INTEGER
-PACKAGE_REF
-
-INTEGER
-REQUIRED
-
-INTEGER
-ENABLED
-
-INTEGER
-
+
+
+SESSION_PACKAGE
+
+[table]
+SESSION_PARTITION_REF
+
+INTEGER
+PACKAGE_REF
+
+INTEGER
+REQUIRED
+
+INTEGER
+ENABLED
+
+INTEGER
+
session_package_61fa13bc:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_61F99F5D
+
+
+
+
+
+
+
session_package_61fa13bc:w->session_partition_f35f84a0:e
-
-
-
-
-
-
-
-SCHCRWLR_F35F1041_61F99F5D
+
+
+
+
+
+
+
spec_27641a:w->package_fab13485:e
-
-
-
-
-
-
-
-SCHCRWLR_FAB0C026_0026EFBB
+
+
+
+
+
+
+
package_extension_default_d8d04687
-
-PACKAGE_EXTENSION_DEFAULT
-
-[table]
-PACKAGE_EXTENSION_REF
-
-INTEGER
-ENTITY_CODE
-
-INTEGER
-ENTITY_QUALIFIER
-
-TEXT
-PARENT_CODE
-
-INTEGER
-MANUFACTURER_CODE
-
-INTEGER
-"VALUE"
-
-TEXT
-
+
+
+PACKAGE_EXTENSION_DEFAULT
+
+[table]
+PACKAGE_EXTENSION_REF
+
+INTEGER
+ENTITY_CODE
+
+INTEGER
+ENTITY_QUALIFIER
+
+TEXT
+PARENT_CODE
+
+INTEGER
+MANUFACTURER_CODE
+
+INTEGER
+"VALUE"
+
+TEXT
+
package_extension_default_d8d04687:w->package_extension_2789e3a5:e
-
-
-
-
-
-
-
-SCHCRWLR_27896F46_D8CFD228
+
+
+
+
+
+
+
package_extension_value_8e65d377
-
-PACKAGE_EXTENSION_VALUE
-
-[table]
-PACKAGE_EXTENSION_VALUE_ID
-
-INTEGER
-
-auto-incremented
-PACKAGE_EXTENSION_REF
-
-INTEGER
-SESSION_REF
-
-INTEGER
-ENTITY_CODE
-
-INTEGER
-PARENT_CODE
-
-INTEGER
-"VALUE"
-
-TEXT
-
+
+
+PACKAGE_EXTENSION_VALUE
+
+[table]
+PACKAGE_EXTENSION_VALUE_ID
+
+INTEGER
+
+auto-incremented
+PACKAGE_EXTENSION_REF
+
+INTEGER
+SESSION_REF
+
+INTEGER
+ENTITY_CODE
+
+INTEGER
+PARENT_CODE
+
+INTEGER
+"VALUE"
+
+TEXT
+
package_extension_value_8e65d377:w->package_extension_2789e3a5:e
-
-
-
-
-
-
-
-SCHCRWLR_27896F46_8E655F18
+
+
+
+
+
+
+
package_extension_value_8e65d377:w->session_a11c82d5:e
-
-
-
-
-
-
-
-SCHCRWLR_A11C0E76_8E655F18
+
+
+
+
+
+
+
user_28582a
-
-"USER"
-
-[table]
-USER_ID
-
-INTEGER
-
-auto-incremented
-USER_KEY
-
-TEXT
-CREATION_TIME
-
-INTEGER
-
+
+
+"USER"
+
+[table]
+USER_ID
+
+INTEGER
+
+auto-incremented
+USER_KEY
+
+TEXT
+CREATION_TIME
+
+INTEGER
+
session_a11c82d5:w->user_28582a:e
-
-
-
-
-
-
-
-SCHCRWLR_3ED95AD5_A11C0E76
+
+
+
+
+
+
+
session_key_value_334d9527
-
-SESSION_KEY_VALUE
-
-[table]
-SESSION_REF
-
-INTEGER
-KEY
-
-TEXT
-"VALUE"
-
-TEXT
-
+
+
+SESSION_KEY_VALUE
+
+[table]
+SESSION_REF
+
+INTEGER
+KEY
+
+TEXT
+"VALUE"
+
+TEXT
+
session_key_value_334d9527:w->session_a11c82d5:e
-
-
-
-
-
-
-
-SCHCRWLR_A11C0E76_334D20C8
+
+
+
+
+
+
+
session_log_7f10ae3a
-
-SESSION_LOG
-
-[table]
-SESSION_REF
-
-INTEGER
-"TIMESTAMP"
-
-TEXT
-LOG
-
-TEXT
-
+
+
+SESSION_LOG
+
+[table]
+SESSION_REF
+
+INTEGER
+"TIMESTAMP"
+
+TEXT
+LOG
+
+TEXT
+
session_log_7f10ae3a:w->session_a11c82d5:e
-
-
-
-
-
-
-
-SCHCRWLR_A11C0E76_7F1039DB
+
+
+
+
+
+
+
session_notice_84addd20
-
-SESSION_NOTICE
-
-[table]
-SESSION_REF
-
-INTEGER
-NOTICE_TYPE
-
-TEXT
-NOTICE_MESSAGE
-
-TEXT
-NOTICE_SEVERITY
-
-INTEGER
-NOTICE_ID
-
-INTEGER
-
-auto-incremented
-DISPLAY
-
-INTEGER
-SEEN
-
-INTEGER
-
+
+
+SESSION_NOTICE
+
+[table]
+SESSION_REF
+
+INTEGER
+NOTICE_TYPE
+
+TEXT
+NOTICE_MESSAGE
+
+TEXT
+NOTICE_SEVERITY
+
+INTEGER
+NOTICE_ID
+
+INTEGER
+
+auto-incremented
+DISPLAY
+
+INTEGER
+SEEN
+
+INTEGER
+
session_notice_84addd20:w->session_a11c82d5:e
-
-
-
-
-
-
-
-SCHCRWLR_A11C0E76_84AD68C1
+
+
+
+
+
+
+
session_partition_f35f84a0:w->session_a11c82d5:e
-
-
-
-
-
-
-
-SCHCRWLR_A11C0E76_F35F1041
+
+
+
+
+
+
+
setting_a12b0e8f
-
-SETTING
-
-[table]
-CATEGORY
-
-TEXT
-KEY
-
-TEXT
-"VALUE"
-
-TEXT
-
+
+
+SETTING
+
+[table]
+CATEGORY
+
+TEXT
+KEY
+
+TEXT
+"VALUE"
+
+TEXT
+
diff --git a/src-electron/db/db-mapping.js b/src-electron/db/db-mapping.js
index 8c8b4258e0..e10a8756dc 100644
--- a/src-electron/db/db-mapping.js
+++ b/src-electron/db/db-mapping.js
@@ -100,6 +100,7 @@ exports.map = {
type: x.TYPE != 'array' ? x.TYPE : x.ARRAY_TYPE,
side: x.SIDE,
define: x.DEFINE,
+ conformance: x.CONFORMANCE,
min: x.MIN,
max: x.MAX,
minLength: x.MIN_LENGTH,
@@ -176,6 +177,7 @@ exports.map = {
name: x.NAME,
description: x.DESCRIPTION,
side: x.SIDE,
+ conformance: x.CONFORMANCE,
isOptional: dbApi.fromDbBool(x.IS_OPTIONAL),
isFabricSensitive: dbApi.fromDbBool(x.IS_FABRIC_SENSITIVE),
priority: x.PRIORITY
@@ -196,6 +198,7 @@ exports.map = {
description: x.DESCRIPTION,
source: x.SOURCE,
isOptional: dbApi.fromDbBool(x.IS_OPTIONAL),
+ conformance: x.CONFORMANCE,
mustUseTimedInvoke: dbApi.fromDbBool(x.MUST_USE_TIMED_INVOKE),
isFabricScoped: dbApi.fromDbBool(x.IS_FABRIC_SCOPED),
clusterCode: x.CLUSTER_CODE,
@@ -251,16 +254,20 @@ exports.map = {
if (x == null) return undefined
return {
deviceType: x.DEVICE_TYPE_NAME,
+ deviceTypeClusterId: x.DEVICE_TYPE_CLUSTER_ID,
+ clusterRef: x.CLUSTER_REF,
cluster: x.CLUSTER_NAME,
includeServer: x.INCLUDE_SERVER,
includeClient: x.INCLUDE_CLIENT,
conformance: x.DEVICE_TYPE_CLUSTER_CONFORMANCE,
- id: x.FEATURE_ID,
+ featureId: x.FEATURE_ID,
name: x.FEATURE_NAME,
code: x.CODE,
bit: x.BIT,
- default_value: x.DEFAULT_VALUE,
- description: x.DESCRIPTION
+ description: x.DESCRIPTION,
+ endpointTypeClusterId: x.ENDPOINT_TYPE_CLUSTER_ID,
+ featureMapAttributeId: x.FEATURE_MAP_ATTRIBUTE_ID,
+ featureMapValue: x.FEATURE_MAP_VALUE
}
},
@@ -585,7 +592,8 @@ exports.map = {
featureName: x.FEATURE_NAME,
featureBit: x.FEATURE_BIT,
clusterId: x.CLUSTER_REF,
- composition: x.TYPE
+ composition: x.TYPE,
+ conformance: x.DEVICE_TYPE_CLUSTER_CONFORMANCE
}
},
endpointTypeCluster: (x) => {
@@ -692,7 +700,10 @@ exports.map = {
type: x.TYPE != 'array' ? x.TYPE : x.ARRAY_TYPE, // Attribute type
apiMaturity: x.API_MATURITY,
isChangeOmitted: dbApi.fromDbBool(x.IS_CHANGE_OMITTED),
- persistence: x.PERSISTENCE
+ persistence: x.PERSISTENCE,
+ reportMinInterval: x.REPORT_MIN_INTERVAL,
+ reportMaxInterval: x.REPORT_MAX_INTERVAL,
+ conformance: x.CONFORMANCE
}
},
@@ -709,6 +720,23 @@ exports.map = {
}
},
+ endpointTypeCommandExtended: (x) => {
+ if (x == null) return undefined
+ return {
+ id: x.COMMAND_ID,
+ name: x.NAME, // Command Name
+ clusterRef: x.CLUSTER_REF,
+ commandRef: x.COMMAND_REF,
+ incoming: dbApi.fromDbBool(x.INCOMING),
+ outgoing: dbApi.fromDbBool(x.OUTGOING),
+ isIncoming: dbApi.fromDbBool(x.IS_INCOMING),
+ source: x.SOURCE,
+ conformance: x.CONFORMANCE,
+ endpointTypeRef: x.ENDPOINT_TYPE_REF,
+ isEnabled: dbApi.fromDbBool(x.IS_ENABLED)
+ }
+ },
+
endpointTypeEvent: (x) => {
if (x == null) return undefined
return {
@@ -719,6 +747,20 @@ exports.map = {
}
},
+ endpointTypeEventExtended: (x) => {
+ if (x == null) return undefined
+ return {
+ id: x.EVENT_ID,
+ name: x.NAME, // Event Name
+ clusterRef: x.CLUSTER_REF,
+ eventRef: x.EVENT_REF,
+ side: x.SIDE,
+ conformance: x.CONFORMANCE,
+ endpointTypeRef: x.ENDPOINT_TYPE_REF,
+ included: dbApi.fromDbBool(x.INCLUDED)
+ }
+ },
+
packageExtension: (x) => {
if (x == null) return undefined
return {
diff --git a/src-electron/db/query-attribute.js b/src-electron/db/query-attribute.js
index a3e10718ba..a817e13af6 100644
--- a/src-electron/db/query-attribute.js
+++ b/src-electron/db/query-attribute.js
@@ -1248,6 +1248,43 @@ async function selectAttributeMappingsByPackageIds(db, packageIds) {
return rows.map(dbMapping.map.attributeMapping)
}
+/**
+ * Get all attributes in an endpoint type cluster
+ * @param {*} db
+ * @param {*} endpointTyeClusterId
+ * @returns all attributes in an endpoint type cluster
+ */
+async function selectAttributesByEndpointTypeClusterId(
+ db,
+ endpointTyeClusterId
+) {
+ let rows = await dbApi.dbAll(
+ db,
+ `
+ SELECT
+ ATTRIBUTE.ATTRIBUTE_ID,
+ ATTRIBUTE.NAME,
+ ATTRIBUTE.CLUSTER_REF,
+ ATTRIBUTE.SIDE,
+ ATTRIBUTE.CONFORMANCE,
+ ATTRIBUTE.REPORT_MIN_INTERVAL,
+ ATTRIBUTE.REPORT_MAX_INTERVAL,
+ ATTRIBUTE.REPORTABLE_CHANGE,
+ ENDPOINT_TYPE_ATTRIBUTE.INCLUDED
+ FROM
+ ATTRIBUTE
+ JOIN
+ ENDPOINT_TYPE_ATTRIBUTE
+ ON
+ ATTRIBUTE.ATTRIBUTE_ID = ENDPOINT_TYPE_ATTRIBUTE.ATTRIBUTE_REF
+ WHERE
+ ENDPOINT_TYPE_ATTRIBUTE.ENDPOINT_TYPE_CLUSTER_REF = ?
+ `,
+ [endpointTyeClusterId]
+ )
+ return rows.map(dbMapping.map.endpointTypeAttributeExtended)
+}
+
exports.selectAllAttributeDetailsFromEnabledClusters = dbCache.cacheQuery(
selectAllAttributeDetailsFromEnabledClusters
)
@@ -1274,3 +1311,5 @@ exports.selectTokenAttributesForEndpoint = selectTokenAttributesForEndpoint
exports.selectAllUserTokenAttributes = selectAllUserTokenAttributes
exports.selectAttributeMappingsByPackageIds =
selectAttributeMappingsByPackageIds
+exports.selectAttributesByEndpointTypeClusterId =
+ selectAttributesByEndpointTypeClusterId
diff --git a/src-electron/db/query-command.js b/src-electron/db/query-command.js
index 97483cd7fb..bc708d9917 100644
--- a/src-electron/db/query-command.js
+++ b/src-electron/db/query-command.js
@@ -1086,6 +1086,7 @@ SELECT
COMMAND.DESCRIPTION,
COMMAND.SOURCE,
COMMAND.IS_OPTIONAL,
+ COMMAND.CONFORMANCE,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
COMMAND.RESPONSE_REF,
@@ -1326,6 +1327,7 @@ SELECT
COMMAND.DESCRIPTION,
COMMAND.SOURCE,
COMMAND.IS_OPTIONAL,
+ COMMAND.CONFORMANCE,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
COMMAND.RESPONSE_REF,
@@ -2046,6 +2048,50 @@ async function selectNonManufacturerSpecificCommandDetailsFromAllEndpointTypesAn
)
}
+/**
+ * Get all commands in an endpoint type cluster
+ * Non-required commands are not loaded into ENDPOINT_TYPE_COMMAND table,
+ * so we need to load all commands by joining DEVICE_TYPE_COMMAND table
+ * @param {*} db
+ * @param {*} endpointTypeClusterId
+ * @param {*} deviceTypeClusterId
+ * @returns all commands in an endpoint type cluster
+ */
+async function selectCommandsByEndpointTypeClusterIdAndDeviceTypeClusterId(
+ db,
+ endpointTypeClusterId,
+ deviceTypeClusterId
+) {
+ let rows = await dbApi.dbAll(
+ db,
+ `
+ SELECT
+ COMMAND.COMMAND_ID,
+ COMMAND.NAME,
+ COMMAND.CLUSTER_REF,
+ COMMAND.SOURCE,
+ COMMAND.CONFORMANCE,
+ COALESCE(ENDPOINT_TYPE_COMMAND.IS_ENABLED, 0) AS IS_ENABLED
+ FROM
+ COMMAND
+ JOIN
+ DEVICE_TYPE_CLUSTER
+ ON
+ COMMAND.CLUSTER_REF = DEVICE_TYPE_CLUSTER.CLUSTER_REF
+ LEFT JOIN
+ ENDPOINT_TYPE_COMMAND
+ ON
+ COMMAND.COMMAND_ID = ENDPOINT_TYPE_COMMAND.COMMAND_REF
+ AND
+ ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF = ?
+ WHERE
+ DEVICE_TYPE_CLUSTER.DEVICE_TYPE_CLUSTER_ID = ?
+ `,
+ [endpointTypeClusterId, deviceTypeClusterId]
+ )
+ return rows.map(dbMapping.map.endpointTypeCommandExtended)
+}
+
exports.selectCliCommandCountFromEndpointTypeCluster =
selectCliCommandCountFromEndpointTypeCluster
exports.selectCliCommandsFromCluster = selectCliCommandsFromCluster
@@ -2098,3 +2144,5 @@ exports.selectAllOutgoingCommandsForCluster =
exports.selectEndpointTypeCommandsByEndpointTypeRefAndClusterRef =
selectEndpointTypeCommandsByEndpointTypeRefAndClusterRef
exports.duplicateEndpointTypeCommand = duplicateEndpointTypeCommand
+exports.selectCommandsByEndpointTypeClusterIdAndDeviceTypeClusterId =
+ selectCommandsByEndpointTypeClusterIdAndDeviceTypeClusterId
diff --git a/src-electron/db/query-config.js b/src-electron/db/query-config.js
index 2437b57c34..35a757b5be 100644
--- a/src-electron/db/query-config.js
+++ b/src-electron/db/query-config.js
@@ -222,14 +222,16 @@ async function insertOrUpdateAttributeState(
staticAttribute.defaultValue == 0
) {
let featureMapDefaultValue = staticAttribute.defaultValue
- let mandatoryFeaturesOnEndpointTypeAndCluster =
+ let featuresOnEndpointTypeAndCluster =
await queryDeviceType.selectDeviceTypeFeaturesByEndpointTypeIdAndClusterId(
db,
endpointTypeId,
clusterRef
)
- let featureMapBitsToBeEnabled =
- mandatoryFeaturesOnEndpointTypeAndCluster.map((f) => f.featureBit)
+ // only set featureMap bit to 1 for mandatory features
+ let featureMapBitsToBeEnabled = featuresOnEndpointTypeAndCluster
+ .filter((f) => f.conformance == 'M')
+ .map((f) => f.featureBit)
featureMapBitsToBeEnabled.forEach(
(featureBit) =>
(featureMapDefaultValue = featureMapDefaultValue | (1 << featureBit))
diff --git a/src-electron/db/query-device-type.js b/src-electron/db/query-device-type.js
index 688848badd..3ba55e365f 100644
--- a/src-electron/db/query-device-type.js
+++ b/src-electron/db/query-device-type.js
@@ -489,7 +489,8 @@ async function selectDeviceTypeFeaturesByEndpointTypeIdAndClusterId(
FEATURE.NAME AS FEATURE_NAME,
FEATURE.CODE AS FEATURE_CODE,
FEATURE.BIT AS FEATURE_BIT,
- DEVICE_TYPE_CLUSTER.CLUSTER_REF
+ DEVICE_TYPE_CLUSTER.CLUSTER_REF,
+ DEVICE_TYPE_FEATURE.DEVICE_TYPE_CLUSTER_CONFORMANCE
FROM
ENDPOINT_TYPE_DEVICE AS ETD
INNER JOIN
diff --git a/src-electron/db/query-event.js b/src-electron/db/query-event.js
index addafd8acf..6e85e11c88 100644
--- a/src-electron/db/query-event.js
+++ b/src-electron/db/query-event.js
@@ -113,6 +113,7 @@ SELECT
NAME,
DESCRIPTION,
SIDE,
+ CONFORMANCE,
IS_OPTIONAL,
IS_FABRIC_SENSITIVE,
PRIORITY
@@ -148,6 +149,7 @@ SELECT
E.NAME,
E.DESCRIPTION,
E.SIDE,
+ E.CONFORMANCE,
E.IS_OPTIONAL,
E.IS_FABRIC_SENSITIVE,
E.PRIORITY
@@ -231,9 +233,56 @@ ORDER BY
.then((rows) => rows.map(dbMapping.map.eventField))
}
+/**
+ * Get all events in an endpoint type cluster
+ * Disabled events are not loaded into ENDPOINT_TYPE_EVENT table,
+ * so we need to load all events by joining DEVICE_TYPE_EVENT table
+ *
+ * @param {*} db
+ * @param {*} endpointTypeClusterId
+ * @param {*} deviceTypeClusterId
+ * @returns all events in an endpoint type cluster
+ */
+async function selectEventsByEndpointTypeClusterIdAndDeviceTypeClusterId(
+ db,
+ endpointTypeClusterId,
+ deviceTypeClusterId
+) {
+ let rows = await dbApi.dbAll(
+ db,
+ `
+ SELECT
+ EVENT.EVENT_ID,
+ EVENT.NAME,
+ EVENT.CLUSTER_REF,
+ EVENT.SIDE,
+ EVENT.CONFORMANCE,
+ COALESCE(ENDPOINT_TYPE_EVENT.INCLUDED, 0) AS INCLUDED
+ FROM
+ EVENT
+ JOIN
+ DEVICE_TYPE_CLUSTER
+ ON
+ EVENT.CLUSTER_REF = DEVICE_TYPE_CLUSTER.CLUSTER_REF
+ LEFT JOIN
+ ENDPOINT_TYPE_EVENT
+ ON
+ EVENT.EVENT_ID = ENDPOINT_TYPE_EVENT.EVENT_REF
+ AND
+ ENDPOINT_TYPE_EVENT.ENDPOINT_TYPE_CLUSTER_REF = ?
+ WHERE
+ DEVICE_TYPE_CLUSTER.DEVICE_TYPE_CLUSTER_ID = ?
+ `,
+ [endpointTypeClusterId, deviceTypeClusterId]
+ )
+ return rows.map(dbMapping.map.endpointTypeEventExtended)
+}
+
exports.selectEventsByClusterId = selectEventsByClusterId
exports.selectAllEvents = selectAllEvents
exports.selectAllEventFields = selectAllEventFields
+exports.selectEventsByEndpointTypeClusterIdAndDeviceTypeClusterId =
+ selectEventsByEndpointTypeClusterIdAndDeviceTypeClusterId
exports.selectEventFieldsByEventId = selectEventFieldsByEventId
exports.selectEndpointTypeEventsByEndpointTypeRefAndClusterRef =
selectEndpointTypeEventsByEndpointTypeRefAndClusterRef
diff --git a/src-electron/db/query-feature.js b/src-electron/db/query-feature.js
index 98f9e64110..60a3045267 100644
--- a/src-electron/db/query-feature.js
+++ b/src-electron/db/query-feature.js
@@ -20,57 +20,616 @@
*
* @module DB API: feature related queries
*/
-const dbApi = require('./db-api.js')
-const dbMapping = require('./db-mapping.js')
+const dbApi = require('./db-api')
+const dbMapping = require('./db-mapping')
/**
- * Get all device type features associated with a list of device type refs
+ * Get all device type features associated with a list of device type refs and an endpoint.
+ * Join ENDPOINT_TYPE_ATTRIBUTE and ATTRIBUTE table to get featureMap attribute associated with the feature,
+ * so the frontend could get and set featureMap bit easier.
+ * Only return features with cluster on the side specified in the device type.
+ *
+ * @export
* @param {*} db
* @param {*} deviceTypeRefs
+ * @param {*} endpointTypeRef
* @returns All feature information and device type conformance
- * with associated device type and cluster details
+ * with associated device type, cluster, and featureMap attribute details
*/
-async function getFeaturesByDeviceTypeRefs(db, deviceTypeRefs) {
+async function getFeaturesByDeviceTypeRefs(
+ db,
+ deviceTypeRefs,
+ endpointTypeRef
+) {
+ let arg = []
let deviceTypeRefsSql = deviceTypeRefs.map(() => '?').join(', ')
+ arg.push(...deviceTypeRefs)
+ arg.push(endpointTypeRef)
let features = await dbApi.dbAll(
db,
`
SELECT
- d.DESCRIPTION AS DEVICE_TYPE_NAME,
- dc.CLUSTER_NAME,
- dc.INCLUDE_SERVER,
- dc.INCLUDE_CLIENT,
- df.DEVICE_TYPE_CLUSTER_CONFORMANCE,
- f.FEATURE_ID,
- f.NAME AS FEATURE_NAME,
- f.CODE,
- f.BIT,
- f.DEFAULT_VALUE,
- f.DESCRIPTION
+ D.DESCRIPTION AS DEVICE_TYPE_NAME,
+ DC.DEVICE_TYPE_CLUSTER_ID,
+ DC.CLUSTER_REF,
+ DC.CLUSTER_NAME,
+ DC.INCLUDE_SERVER,
+ DC.INCLUDE_CLIENT,
+ DF.DEVICE_TYPE_CLUSTER_CONFORMANCE,
+ F.FEATURE_ID,
+ F.NAME AS FEATURE_NAME,
+ F.CODE,
+ F.BIT,
+ F.DESCRIPTION,
+ ETC.ENDPOINT_TYPE_CLUSTER_ID,
+ ETA.ENDPOINT_TYPE_ATTRIBUTE_ID AS FEATURE_MAP_ATTRIBUTE_ID,
+ ETA.DEFAULT_VALUE AS FEATURE_MAP_VALUE
FROM
- DEVICE_TYPE d
+ DEVICE_TYPE D
JOIN
- DEVICE_TYPE_CLUSTER dc
+ DEVICE_TYPE_CLUSTER DC
ON
- d.DEVICE_TYPE_ID = dc.DEVICE_TYPE_REF
+ D.DEVICE_TYPE_ID = DC.DEVICE_TYPE_REF
JOIN
- DEVICE_TYPE_FEATURE df
+ DEVICE_TYPE_FEATURE DF
ON
- dc.DEVICE_TYPE_CLUSTER_ID = df.DEVICE_TYPE_CLUSTER_REF
+ DC.DEVICE_TYPE_CLUSTER_ID = DF.DEVICE_TYPE_CLUSTER_REF
+ JOIN
+ FEATURE F
+ ON
+ DF.FEATURE_REF = F.FEATURE_ID
+ JOIN
+ ENDPOINT_TYPE_CLUSTER ETC
+ ON
+ DC.CLUSTER_REF = ETC.CLUSTER_REF
JOIN
- FEATURE f
+ ENDPOINT_TYPE_ATTRIBUTE ETA
ON
- df.FEATURE_REF = f.FEATURE_ID
+ ETC.ENDPOINT_TYPE_CLUSTER_ID = ETA.ENDPOINT_TYPE_CLUSTER_REF
+ JOIN
+ ATTRIBUTE A
+ ON
+ ETA.ATTRIBUTE_REF = A.ATTRIBUTE_ID
WHERE
- d.DEVICE_TYPE_ID IN (${deviceTypeRefsSql})
+ D.DEVICE_TYPE_ID IN (${deviceTypeRefsSql})
+ AND
+ ETC.ENDPOINT_TYPE_REF = ?
+ AND
+ A.NAME = 'FeatureMap'
+ AND
+ A.CODE = 65532
+ AND
+ (
+ (DC.INCLUDE_SERVER = 1 AND ETC.SIDE = 'server')
+ OR
+ (DC.INCLUDE_CLIENT = 1 AND ETC.SIDE = 'client')
+ )
ORDER BY
- d.DEVICE_TYPE_ID,
- dc.CLUSTER_REF,
- f.FEATURE_ID
+ D.DEVICE_TYPE_ID,
+ DC.CLUSTER_REF,
+ F.FEATURE_ID
`,
- deviceTypeRefs
+ arg
)
return features.map(dbMapping.map.deviceTypeFeature)
}
+/**
+ * Evaluate the value of a boolean conformance expression that includes terms and operators.
+ * A term can be an attribute, command, event, feature, or conformance abbreviation.
+ * Operators include AND (&), OR (|), and NOT (!).
+ * The '[]' indicates optional conformance if the expression inside true.
+ * Expression containing comma means otherwise conformance. See spec for details.
+ * Examples of conformance expression: 'A & (!B | C)', 'A & B, [!C]'
+ *
+ * @export
+ * @param {*} expression
+ * @param {*} elementMap
+ * @returns 'mandatory', 'optional', 'provisional', or 'notSupported'
+ */
+function evaluateConformanceExpression(expression, elementMap) {
+ /**
+ * helper function to evaluate a single boolean expression
+ * @param {*} expr
+ */
+ function evaluateBooleanExpression(expr) {
+ // Replace terms with their actual values from elementMap
+ expr = expr.replace(/[A-Za-z][A-Za-z0-9]*/g, (term) => {
+ if (elementMap[term]) {
+ return 'true'
+ } else {
+ return 'false'
+ }
+ })
+
+ // Evaluate NOT (!) operators
+ expr = expr.replace(/!true/g, 'false').replace(/!false/g, 'true')
+
+ // Evaluate AND (&) and OR (|) operators by eval() function
+ return eval(expr)
+ }
+
+ /**
+ * helper function to process parentheses and evaluate inner expressions first
+ * @param {*} expr
+ */
+ function evaluateWithParentheses(expr) {
+ while (expr.includes('(')) {
+ expr = expr.replace(/\([^()]+\)/g, (terms) =>
+ evaluateBooleanExpression(terms.slice(1, -1))
+ )
+ }
+ return evaluateBooleanExpression(expr)
+ }
+
+ // Check ',' for otherwise conformance first.
+ // Split the expression by ',' and evaluate each part in sequence
+ let parts = expression.split(',')
+ // if any term is desc, the conformance is too complex to parse
+ for (let part of parts) {
+ let terms = part.match(/[A-Za-z][A-Za-z0-9]*/g)
+ if (terms && terms.includes('desc')) {
+ return 'desc'
+ }
+ }
+ for (let part of parts) {
+ if (part.includes('[') && part.includes(']')) {
+ // Extract and evaluate the content inside '[]'
+ let optionalExpr = part.match(/\[(.*?)\]/)[1]
+ let optionalResult = evaluateWithParentheses(optionalExpr)
+ if (optionalResult) {
+ return 'optional'
+ } else {
+ return 'notSupported'
+ }
+ } else {
+ part = part.trim()
+ if (part == 'M') {
+ return 'mandatory'
+ } else if (part == 'O') {
+ return 'optional'
+ } else if (part == 'D' || part == 'X') {
+ return 'notSupported'
+ } else if (part == 'P') {
+ return 'provisional'
+ } else {
+ // Evaluate the part with parentheses if needed
+ let result = evaluateWithParentheses(part)
+ if (result) return 'mandatory'
+ // if the mandatory part is false, go to the next part
+ }
+ }
+ }
+
+ // If none of the parts are true and no optional part was valid, return 'notSupported'
+ return 'notSupported'
+}
+
+/**
+ * Check if any terms in the expression are neither a key in the elementMap nor an abbreviation.
+ * If so, it means the conformance depends on terms with unknown values and changes are not allowed.
+ *
+ * @param {*} expression
+ * @param {*} elementMap
+ * @returns all missing terms in an array
+ */
+function checkMissingTerms(expression, elementMap) {
+ let terms = expression.match(/[A-Za-z][A-Za-z0-9]*/g)
+ let missingTerms = []
+ let abbreviations = ['M', 'O', 'P', 'D', 'X']
+ for (let term of terms) {
+ if (!(term in elementMap) && !abbreviations.includes(term)) {
+ missingTerms.push(term)
+ }
+ }
+ return missingTerms
+}
+
+/**
+ * Filter an array of elements by if any element has conformance containing the term 'desc'.
+ *
+ * @export
+ * @param {*} elements
+ * @returns elements with conformance containing 'desc'
+ */
+function filterElementsContainingDesc(elements) {
+ return elements.filter((element) => {
+ let terms = element.conformance.match(/[A-Za-z][A-Za-z0-9]*/g)
+ return terms && terms.includes('desc')
+ })
+}
+
+/**
+ *
+ * @export
+ * @param {*} elements
+ * @param {*} featureCode
+ * @returns elements with conformance containing 'desc' and the feature code
+ */
+function filterRelatedDescElements(elements, featureCode) {
+ return elements.filter((element) => {
+ let terms = element.conformance.match(/[A-Za-z][A-Za-z0-9]*/g)
+ return terms && terms.includes('desc') && terms.includes(featureCode)
+ })
+}
+
+/**
+ * Generate a warning message after processing conformance of the updated device type feature.
+ * Set flags to decide whether to show a popup warning or disable changes in the frontend.
+ *
+ * @param {*} featureData
+ * @param {*} endpointId
+ * @param {*} missingTerms
+ * @param {*} featureMap
+ * @param {*} descElements
+ * @returns warning message array, disableChange flag, and displayWarning flag
+ */
+function generateWarningMessage(
+ featureData,
+ endpointId,
+ missingTerms,
+ featureMap,
+ descElements
+) {
+ let featureName = featureData.name
+ let added = featureMap[featureData.code] ? true : false
+ let deviceTypeNames = featureData.deviceTypes.join(', ')
+ let result = {
+ warningMessage: '',
+ disableChange: true,
+ displayWarning: true
+ }
+ result.warningMessage = []
+
+ if (missingTerms.length > 0) {
+ let missingTermsString = missingTerms.join(', ')
+ result.warningMessage.push(
+ 'On Endpoint ' +
+ endpointId +
+ ', feature ' +
+ featureName +
+ ' cannot be enabled as its conformance depends on non device type features ' +
+ missingTermsString +
+ ' with unknown values'
+ )
+ }
+
+ if (
+ (descElements.attributes && descElements.attributes.length > 0) ||
+ (descElements.commands && descElements.commands.length > 0) ||
+ (descElements.events && descElements.events.length > 0)
+ ) {
+ let attributeNames = descElements.attributes
+ .map((attr) => attr.name)
+ .join(', ')
+ let commandNames = descElements.commands
+ .map((command) => command.name)
+ .join(', ')
+ let eventNames = descElements.events.map((event) => event.name).join(', ')
+ result.warningMessage.push(
+ 'On endpoint ' +
+ endpointId +
+ ', feature ' +
+ featureName +
+ ' cannot be enabled as ' +
+ (attributeNames ? 'attribute ' + attributeNames : '') +
+ (attributeNames && commandNames ? ', ' : '') +
+ (commandNames ? 'command ' + commandNames : '') +
+ ((attributeNames || commandNames) && eventNames ? ', ' : '') +
+ (eventNames ? 'event ' + eventNames : '') +
+ ' depend on the feature and their conformance are too complex to parse.'
+ )
+ }
+
+ if (
+ missingTerms.length == 0 &&
+ descElements.attributes.length == 0 &&
+ descElements.commands.length == 0 &&
+ descElements.events.length == 0
+ ) {
+ let conformance = evaluateConformanceExpression(
+ featureData.conformance,
+ featureMap
+ )
+ // change is not disabled, by default does not display warning
+ result.disableChange = false
+ result.displayWarning = false
+ // in this case only 1 warning message is needed
+ result.warningMessage = ''
+ if (conformance == 'notSupported') {
+ result.warningMessage =
+ 'On endpoint ' +
+ endpointId +
+ ', feature ' +
+ featureName +
+ ' is enabled, but it is not supported for device type ' +
+ deviceTypeNames
+ result.displayWarning = added
+ }
+ if (conformance == 'provisional') {
+ result.warningMessage =
+ 'On endpoint ' +
+ endpointId +
+ ', feature ' +
+ featureName +
+ ' is enabled, but it is still provisional for device type ' +
+ deviceTypeNames
+ result.displayWarning = added
+ }
+ if (conformance == 'mandatory') {
+ result.warningMessage =
+ 'On endpoint ' +
+ endpointId +
+ ', feature ' +
+ featureName +
+ ' is disabled, but it is mandatory for device type ' +
+ deviceTypeNames
+ result.displayWarning = !added
+ }
+ }
+
+ return result
+}
+
+/**
+ * Check if elements need to be updated for correct conformance if featureData provided.
+ * Otherwise, check if elements are required or unsupported by their conformance.
+ *
+ * @export
+ * @param {*} elements
+ * @param {*} featureMap
+ * @param {*} featureData
+ * @param {*} endpointId
+ * @returns attributes, commands, and events to update, with warnings if featureData provided;
+ * required and unsupported attributes, commands, and events, with warnings if not.
+ */
+function checkElementConformance(
+ elements,
+ featureMap,
+ featureData = null,
+ endpointId = null
+) {
+ let { attributes, commands, events } = elements
+ let featureCode = featureData ? featureData.code : ''
+
+ // create a map of element names/codes to their enabled status
+ let elementMap = featureMap
+ attributes.forEach((attribute) => {
+ elementMap[attribute.name] = attribute.included
+ })
+ commands.forEach((command) => {
+ elementMap[command.name] = command.isEnabled
+ })
+ events.forEach((event) => {
+ elementMap[event.name] = event.included
+ })
+ elementMap['Matter'] = 1
+ elementMap['Zigbee'] = 0
+
+ let warningInfo = {}
+ if (featureData != null) {
+ let descElements = {}
+ descElements.attributes = filterRelatedDescElements(attributes, featureCode)
+ descElements.commands = filterRelatedDescElements(commands, featureCode)
+ descElements.events = filterRelatedDescElements(events, featureCode)
+
+ let missingTerms = checkMissingTerms(featureData.conformance, elementMap)
+ warningInfo = generateWarningMessage(
+ featureData,
+ endpointId,
+ missingTerms,
+ featureMap,
+ descElements
+ )
+
+ if (warningInfo.disableChange) {
+ return {
+ ...warningInfo,
+ attributesToUpdate: [],
+ commandsToUpdate: [],
+ eventsToUpdate: []
+ }
+ }
+ }
+
+ // check element conformance for if they need update or are required
+ let attributesToUpdate = featureData
+ ? filterElementsToUpdate(attributes, elementMap, featureCode)
+ : filterRequiredElements(attributes, elementMap, featureMap)
+ let commandsToUpdate = featureData
+ ? filterElementsToUpdate(commands, elementMap, featureCode)
+ : filterRequiredElements(commands, elementMap, featureMap)
+ let eventsToUpdate = featureData
+ ? filterElementsToUpdate(events, elementMap, featureCode)
+ : filterRequiredElements(events, elementMap, featureMap)
+
+ let result = {
+ attributesToUpdate: attributesToUpdate,
+ commandsToUpdate: commandsToUpdate,
+ eventsToUpdate: eventsToUpdate,
+ elementMap: elementMap
+ }
+ return featureData ? { ...warningInfo, ...result } : result
+}
+
+/**
+ * Return attributes, commands, or events to be updated satisfying:
+ * (1) its conformance includes feature code of the updated feature
+ * (2) it has mandatory conformance but it is not enabled, OR,
+ * it is has notSupported conformance but it is enabled
+ *
+ * @param {*} elements
+ * @param {*} elementMap
+ * @param {*} featureCode
+ * @returns elements that should be updated
+ */
+function filterElementsToUpdate(elements, elementMap, featureCode) {
+ let elementsToUpdate = []
+ elements
+ .filter((element) => element.conformance.includes(featureCode))
+ .forEach((element) => {
+ let conformance = evaluateConformanceExpression(
+ element.conformance,
+ elementMap
+ )
+ if (
+ conformance == 'mandatory' &&
+ (!elementMap[element.name] || elementMap[element.name] == 0)
+ ) {
+ element.value = true
+ elementsToUpdate.push(element)
+ }
+ if (conformance == 'notSupported' && elementMap[element.name]) {
+ element.value = false
+ elementsToUpdate.push(element)
+ }
+ })
+ return elementsToUpdate
+}
+
+/**
+ * Get warnings for element requirements that are outdated after a feature update.
+ *
+ * @param {*} featureData
+ * @param {*} elements
+ * @param {*} elementMap
+ * @returns array of outdated element warnings
+ */
+function getOutdatedElementWarning(featureData, elements, elementMap) {
+ let outdatedWarnings = []
+
+ /**
+ * Build substrings of outdated warnings and add to returned array if:
+ * (1) the element conformance includes the feature code
+ * (2) the element conformance has changed after the feature update
+ *
+ * @param {*} elementType
+ */
+ function processElements(elementType) {
+ elements[elementType].forEach((element) => {
+ if (element.conformance.includes(featureData.code)) {
+ let newConform = evaluateConformanceExpression(
+ element.conformance,
+ elementMap
+ )
+ let oldMap = { ...elementMap }
+ oldMap[featureData.code] = !oldMap[featureData.code]
+ let oldConform = evaluateConformanceExpression(
+ element.conformance,
+ oldMap
+ )
+ if (newConform != oldConform) {
+ let pattern = `${element.name} conforms to ${element.conformance} and is`
+ outdatedWarnings.push(pattern)
+ }
+ }
+ })
+ }
+
+ processElements('attributes')
+ processElements('commands')
+ processElements('events')
+
+ return outdatedWarnings
+}
+
+/**
+ * Filter required and unsupported elements based on their conformance and generate warnings.
+ * An element is required if it conforms to element(s) in elementMap and has 'mandatory' conform.
+ * An element is unsupported if it conforms to element(s) in elementMap and has 'notSupported' conform.
+ *
+ * @param {*} elements
+ * @param {*} elementMap
+ * @param {*} featureMap
+ * @returns required and not supported elements with warnings
+ */
+function filterRequiredElements(elements, elementMap, featureMap) {
+ let requiredElements = {
+ required: {},
+ notSupported: {}
+ }
+ elements.forEach((element) => {
+ let conformance = evaluateConformanceExpression(
+ element.conformance,
+ elementMap
+ )
+ let expression = element.conformance
+ let terms = expression ? expression.match(/[A-Za-z][A-Za-z0-9]*/g) : []
+ let featureTerms = terms.filter((term) => term in featureMap).join(', ')
+ let elementTerms = terms.filter((term) => !(term in featureMap)).join(', ')
+ let conformToElement = terms.some((term) =>
+ Object.keys(elementMap).includes(term)
+ )
+
+ if (conformToElement) {
+ let conformState = ''
+ if (conformance == 'mandatory') {
+ conformState = 'mandatory'
+ }
+ if (conformance == 'notSupported') {
+ conformState = 'not supported'
+ }
+
+ // generate warning message for required and unsupported elements
+ element.warningMessage =
+ `${element.name} conforms to ${element.conformance} and is ` +
+ `${conformState}` +
+ (featureTerms ? ` based on state of feature: ${featureTerms}` : '') +
+ (featureTerms && elementTerms ? ', ' : '') +
+ (elementTerms ? `element: ${elementTerms}` : '') +
+ '.'
+ if (conformance == 'mandatory') {
+ requiredElements.required[element.id] = element.warningMessage
+ }
+ if (conformance == 'notSupported') {
+ requiredElements.notSupported[element.id] = element.warningMessage
+ }
+ }
+ })
+ return requiredElements
+}
+
+/**
+ * Check if any non-empty conformance data exist in ATTRIBUTE, COMMAND,
+ * and DEVICE_TYPE_FEATURE table.
+ *
+ * @export
+ * @param {*} db
+ * @returns boolean value indicating if conformance data exists
+ */
+async function checkIfConformanceDataExist(db) {
+ try {
+ let deviceTypeFeatureRows = await dbApi.dbAll(
+ db,
+ 'SELECT DEVICE_TYPE_CLUSTER_CONFORMANCE FROM DEVICE_TYPE_FEATURE'
+ )
+ let hasFeatureConformanceData = deviceTypeFeatureRows.some((row) => {
+ return (
+ row.DEVICE_TYPE_CLUSTER_CONFORMANCE &&
+ row.DEVICE_TYPE_CLUSTER_CONFORMANCE.trim() != ''
+ )
+ })
+ let attributeRows = await dbApi.dbAll(
+ db,
+ 'SELECT CONFORMANCE FROM ATTRIBUTE'
+ )
+ let commandRows = await dbApi.dbAll(db, 'SELECT CONFORMANCE FROM COMMAND')
+ let hasConformanceData = (rows) =>
+ rows.some((row) => row.CONFORMANCE && row.CONFORMANCE.trim() != '')
+ return (
+ hasConformanceData(attributeRows) &&
+ hasConformanceData(commandRows) &&
+ hasFeatureConformanceData
+ )
+ } catch (err) {
+ return false
+ }
+}
+
exports.getFeaturesByDeviceTypeRefs = getFeaturesByDeviceTypeRefs
+exports.checkElementConformance = checkElementConformance
+exports.evaluateConformanceExpression = evaluateConformanceExpression
+exports.filterElementsContainingDesc = filterElementsContainingDesc
+exports.filterRelatedDescElements = filterRelatedDescElements
+exports.checkIfConformanceDataExist = checkIfConformanceDataExist
+exports.getOutdatedElementWarning = getOutdatedElementWarning
diff --git a/src-electron/db/query-loader.js b/src-electron/db/query-loader.js
index 95f1bbe127..47e05882f9 100644
--- a/src-electron/db/query-loader.js
+++ b/src-electron/db/query-loader.js
@@ -59,13 +59,14 @@ INSERT INTO EVENT (
NAME,
DESCRIPTION,
SIDE,
+ CONFORMANCE,
IS_OPTIONAL,
IS_FABRIC_SENSITIVE,
PRIORITY,
INTRODUCED_IN_REF,
REMOVED_IN_REF
) VALUES (
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
(SELECT SPEC_ID FROM SPEC WHERE CODE = ? AND PACKAGE_REF = ?),
(SELECT SPEC_ID FROM SPEC WHERE CODE = ? AND PACKAGE_REF = ?)
)
@@ -96,6 +97,7 @@ INSERT INTO COMMAND (
DESCRIPTION,
SOURCE,
IS_OPTIONAL,
+ CONFORMANCE,
MUST_USE_TIMED_INVOKE,
IS_FABRIC_SCOPED,
RESPONSE_NAME,
@@ -105,7 +107,7 @@ INSERT INTO COMMAND (
IS_DEFAULT_RESPONSE_ENABLED,
IS_LARGE_MESSAGE
) VALUES (
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
(SELECT SPEC_ID FROM SPEC WHERE CODE = ? AND PACKAGE_REF = ?),
(SELECT SPEC_ID FROM SPEC WHERE CODE = ? AND PACKAGE_REF = ?),
?, ?
@@ -146,6 +148,7 @@ INSERT INTO ATTRIBUTE (
TYPE,
SIDE,
DEFINE,
+ CONFORMANCE,
MIN,
MAX,
MIN_LENGTH,
@@ -170,7 +173,7 @@ INSERT INTO ATTRIBUTE (
IS_CHANGE_OMITTED,
PERSISTENCE
) VALUES (
- ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
+ ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
(SELECT SPEC_ID FROM SPEC WHERE CODE = ? AND PACKAGE_REF = ?),
(SELECT SPEC_ID FROM SPEC WHERE CODE = ? AND PACKAGE_REF = ?),
?,
@@ -222,6 +225,7 @@ function attributeMap(clusterId, packageId, attributes) {
attribute.type,
attribute.side,
attribute.define,
+ attribute.conformance,
attribute.min,
attribute.max,
attribute.minLength,
@@ -267,6 +271,7 @@ function eventMap(clusterId, packageId, events) {
event.name,
event.description,
event.side,
+ event.conformance,
dbApi.toDbBool(event.isOptional),
dbApi.toDbBool(event.isFabricSensitive),
event.priority,
@@ -294,6 +299,7 @@ function commandMap(clusterId, packageId, commands) {
command.description,
command.source,
dbApi.toDbBool(command.isOptional),
+ command.conformance,
dbApi.toDbBool(command.mustUseTimedInvoke),
dbApi.toDbBool(command.isFabricScoped),
command.responseName,
diff --git a/src-electron/db/query-session-notification.js b/src-electron/db/query-session-notification.js
index 1b0bec4d86..159d9f96a2 100644
--- a/src-electron/db/query-session-notification.js
+++ b/src-electron/db/query-session-notification.js
@@ -83,13 +83,11 @@ async function setNotification(
}
/**
- * Deletes a notification from the SESSION_NOTICE table
+ * Deletes a notification from the SESSION_NOTICE table by NOTICE_ID
*
* @export
* @param {*} db
- * @param {*} sessionId
- * @param {*} type
- * @param {*} message
+ * @param {*} id
*/
async function deleteNotification(db, id) {
return dbApi.dbUpdate(
@@ -133,11 +131,11 @@ async function getUnseenNotificationCount(db, sessionId) {
}
/**
- * update SEEN column to 1 for all notifications from the SESSION_NOTICE table with NOTIC_ORDER inside given input array unseenIds
+ * update SEEN column to 1 for all notifications from the SESSION_NOTICE table with NOTICE_ID inside given input array unseenIds
*
* @export
* @param {*} db
- * @param {*} sessionId
+ * @param {*} unseenIds
*/
async function markNotificationsAsSeen(db, unseenIds) {
if (unseenIds && unseenIds.length > 0) {
@@ -150,10 +148,158 @@ async function markNotificationsAsSeen(db, unseenIds) {
}
}
+/**
+ * search for notifications with given message and delete them if found
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @param {*} message
+ * @returns db delete promise if notification(s) were found and deleted, false otherwise
+ */
+async function searchNotificationByMessageAndDelete(db, sessionId, message) {
+ let rows = await dbApi.dbAll(
+ db,
+ 'SELECT NOTICE_ID FROM SESSION_NOTICE WHERE SESSION_REF = ? AND NOTICE_MESSAGE = ?',
+ [sessionId, message]
+ )
+ if (rows && rows.length > 0) {
+ let ids = rows.map((row) => row.NOTICE_ID)
+ let deleteResponses = []
+ for (let id of ids) {
+ let response = await deleteNotification(db, id)
+ deleteResponses.push(response)
+ }
+ return deleteResponses
+ }
+ return false
+}
+
+/**
+ * check if notification with given message exists and if not, create a new one with type WARNING
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @param {*} message
+ * @returns setNotification response if message does not exist and notification was set, false otherwise
+ */
+async function setWarningIfMessageNotExists(db, sessionId, message) {
+ let rows = await dbApi.dbAll(
+ db,
+ 'SELECT NOTICE_ID FROM SESSION_NOTICE WHERE SESSION_REF = ? AND NOTICE_MESSAGE = ?',
+ [sessionId, message]
+ )
+ if (rows && rows.length == 0) {
+ return setNotification(db, 'WARNING', message, sessionId, 2, 0)
+ }
+ return false
+}
+
+/**
+ * Set or delete warning notification after updating a device type feature.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} sessionId
+ * @param {*} result
+ */
+async function setNotificationOnFeatureChange(db, sessionId, result) {
+ let { warningMessage, disableChange, displayWarning } = result
+ if (disableChange) {
+ for (let message of warningMessage) {
+ await setWarningIfMessageNotExists(db, sessionId, message)
+ }
+ return
+ }
+ if (displayWarning) {
+ await setNotification(db, 'WARNING', warningMessage, sessionId, 2, 0)
+ } else {
+ await searchNotificationByMessageAndDelete(db, sessionId, warningMessage)
+ }
+}
+
+/**
+ * Set warning for the required element. Delete previous warning for the element if exists.
+ *
+ * @export
+ * @param {*} db
+ * @param {*} data
+ * @param {*} sessionId
+ * @returns response of setting warning notification
+ */
+async function setRequiredElementWarning(db, data, sessionId) {
+ let { element, contextMessage, requiredText, notSupportedText, added } = data
+
+ // delete previous warning before setting new one
+ let patterns = [`${element.name} conforms to ${element.conformance} and is`]
+ await deleteNotificationWithPatterns(db, sessionId, patterns)
+
+ let addResp = false
+ if (requiredText && !added) {
+ addResp = await setWarningIfMessageNotExists(
+ db,
+ sessionId,
+ contextMessage + requiredText
+ )
+ }
+ if (notSupportedText && added) {
+ addResp = await setWarningIfMessageNotExists(
+ db,
+ sessionId,
+ contextMessage + notSupportedText
+ )
+ }
+ return addResp
+}
+
+/**
+ * Delete notifications with message containing substrings specified in the patterns array.
+ *
+ * @param {*} db
+ * @param {*} sessionId
+ * @param {*} patterns
+ * @returns response of deleting notifications
+ */
+async function deleteNotificationWithPatterns(db, sessionId, patterns) {
+ if (!Array.isArray(patterns) || patterns.length == 0) return false
+
+ let placeholders = patterns.map(() => '?').join(' OR NOTICE_MESSAGE LIKE ')
+ let query = `
+ SELECT
+ NOTICE_ID
+ FROM
+ SESSION_NOTICE
+ WHERE
+ SESSION_REF = ?
+ AND (
+ NOTICE_MESSAGE LIKE ${placeholders}
+ )
+ `
+ let params = [sessionId, ...patterns.map((pattern) => `%${pattern}%`)]
+
+ let rows = await dbApi.dbAll(db, query, params)
+ if (rows && rows.length > 0) {
+ let ids = rows.map((row) => row.NOTICE_ID)
+ let deleteResponses = []
+ for (let id of ids) {
+ let response = await deleteNotification(db, id)
+ deleteResponses.push(response)
+ }
+ return deleteResponses
+ }
+ return false
+}
+
// exports
exports.setNotification = setNotification
exports.deleteNotification = deleteNotification
exports.getNotification = getNotification
exports.getUnseenNotificationCount = getUnseenNotificationCount
exports.markNotificationsAsSeen = markNotificationsAsSeen
-//# sourceMappingURL=query-session-notification.js.map
+exports.searchNotificationByMessageAndDelete =
+ searchNotificationByMessageAndDelete
+exports.setWarningIfMessageNotExists = setWarningIfMessageNotExists
+exports.setNotificationOnFeatureChange = setNotificationOnFeatureChange
+exports.setRequiredElementWarning = setRequiredElementWarning
+exports.deleteNotificationWithPatterns = deleteNotificationWithPatterns
diff --git a/src-electron/db/query-zcl.js b/src-electron/db/query-zcl.js
index ce134d51d9..567e371e46 100644
--- a/src-electron/db/query-zcl.js
+++ b/src-electron/db/query-zcl.js
@@ -694,6 +694,7 @@ SELECT
TYPE,
SIDE,
DEFINE,
+ CONFORMANCE,
MIN,
MAX,
MIN_LENGTH,
@@ -988,6 +989,7 @@ SELECT
A.TYPE,
A.SIDE,
A.DEFINE,
+ A.CONFORMANCE,
A.MIN,
A.MAX,
A.MIN_LENGTH,
diff --git a/src-electron/db/zap-schema.sql b/src-electron/db/zap-schema.sql
index a87f3c888f..870783920a 100644
--- a/src-electron/db/zap-schema.sql
+++ b/src-electron/db/zap-schema.sql
@@ -176,6 +176,7 @@ CREATE TABLE IF NOT EXISTS "COMMAND" (
"DESCRIPTION" text,
"SOURCE" text,
"IS_OPTIONAL" integer,
+ "CONFORMANCE" text,
"MUST_USE_TIMED_INVOKE" integer,
"IS_FABRIC_SCOPED" integer,
"INTRODUCED_IN_REF" integer,
@@ -230,6 +231,7 @@ CREATE TABLE IF NOT EXISTS "EVENT" (
"NAME" text,
"DESCRIPTION" text,
"SIDE" text,
+ "CONFORMANCE" text,
"IS_OPTIONAL" integer,
"IS_FABRIC_SENSITIVE" integer,
"PRIORITY" text,
@@ -275,6 +277,7 @@ CREATE TABLE IF NOT EXISTS "ATTRIBUTE" (
"TYPE" text,
"SIDE" text,
"DEFINE" text,
+ "CONFORMANCE" text,
"MIN" text,
"MAX" text,
"MIN_LENGTH" integer,
diff --git a/src-electron/rest/user-data.js b/src-electron/rest/user-data.js
index cc154529f7..6fa1174ed3 100644
--- a/src-electron/rest/user-data.js
+++ b/src-electron/rest/user-data.js
@@ -84,12 +84,123 @@ function httpGetEndpointIds(db) {
*/
function httpGetDeviceTypeFeatures(db) {
return async (request, response) => {
- let deviceTypeRefs = request.query.deviceTypeRefs
- let deviceTypeFeatures = await queryFeature.getFeaturesByDeviceTypeRefs(
+ let { deviceTypeRefs, endpointTypeRef } = request.query
+ if (Array.isArray(deviceTypeRefs) && deviceTypeRefs.length > 0) {
+ let deviceTypeFeatures = await queryFeature.getFeaturesByDeviceTypeRefs(
+ db,
+ deviceTypeRefs,
+ endpointTypeRef
+ )
+ response.status(StatusCodes.OK).json(deviceTypeFeatures)
+ } else {
+ response.status(StatusCodes.OK).json([])
+ }
+ }
+}
+
+/**
+ * Get all attributes, commands and events in an endpoint type cluster.
+ * @param {*} db
+ * @param {*} endpointTypeClusterId
+ * @param {*} deviceTypeClusterId
+ * @returns elements object containing all attributes, commands and events
+ * in an endpoint type cluster
+ */
+async function getEndpointTypeElements(
+ db,
+ endpointTypeClusterId,
+ deviceTypeClusterId
+) {
+ let [attributes, commands, events] = await Promise.all([
+ queryAttribute.selectAttributesByEndpointTypeClusterId(
+ db,
+ endpointTypeClusterId
+ ),
+ queryCommand.selectCommandsByEndpointTypeClusterIdAndDeviceTypeClusterId(
db,
- deviceTypeRefs
+ endpointTypeClusterId,
+ deviceTypeClusterId
+ ),
+ queryEvent.selectEventsByEndpointTypeClusterIdAndDeviceTypeClusterId(
+ db,
+ endpointTypeClusterId,
+ deviceTypeClusterId
)
- response.status(StatusCodes.OK).json(deviceTypeFeatures)
+ ])
+ return { attributes, commands, events }
+}
+
+/**
+ * HTTP POST: elements to be updated after toggle a device type feature
+ *
+ * @param {*} db
+ * @returns callback for the express uri registration
+ */
+function httpPostCheckConformOnFeatureUpdate(db) {
+ return async (request, response) => {
+ let sessionId = request.zapSessionId
+ let { featureData, featureMap, endpointId } = request.body
+ let { endpointTypeClusterId, deviceTypeClusterId } = featureData
+
+ let elements = await getEndpointTypeElements(
+ db,
+ endpointTypeClusterId,
+ deviceTypeClusterId
+ )
+ // check element conform and return elements that need to be updated
+ let result = queryFeature.checkElementConformance(
+ elements,
+ featureMap,
+ featureData,
+ endpointId
+ )
+
+ // set device type feature warning
+ await querySessionNotification.setNotificationOnFeatureChange(
+ db,
+ sessionId,
+ result
+ )
+ // do not set element warning if feature change disabled
+ if (!result.disableChange) {
+ let outdatedWarnings = queryFeature.getOutdatedElementWarning(
+ featureData,
+ elements,
+ result.elementMap
+ )
+ await querySessionNotification.deleteNotificationWithPatterns(
+ db,
+ sessionId,
+ outdatedWarnings
+ )
+ }
+
+ response.status(StatusCodes.OK).json(result)
+ }
+}
+
+/**
+ * HTTP GET: required and unsupported cluster elements based on conformance
+ * @param {*} db
+ * @returns callback for the express uri registration
+ */
+function httpGetRequiredElements(db) {
+ return async (request, response) => {
+ let { featureMap, deviceTypeClusterId, endpointTypeClusterId } = JSON.parse(
+ request.query.data
+ )
+ featureMap = JSON.parse(featureMap)
+ let endpointTypeElements = await getEndpointTypeElements(
+ db,
+ endpointTypeClusterId,
+ deviceTypeClusterId
+ )
+ let result = queryFeature.checkElementConformance(
+ endpointTypeElements,
+ featureMap
+ )
+
+ response.status(StatusCodes.OK).json(result)
}
}
@@ -1008,6 +1119,58 @@ function httpPostDuplicateEndpointType(db) {
}
}
+/**
+ * Update feature map attribute with given new value
+ *
+ * @param {*} db
+ * @returns status of the update
+ */
+function httpPatchUpdateBitOfFeatureMapAttribute(db) {
+ return async (request, response) => {
+ let { featureMapAttributeId, newValue } = request.body
+ let updated = await queryConfig.updateEndpointTypeAttribute(
+ db,
+ featureMapAttributeId,
+ [['defaultValue', newValue]]
+ )
+ response.status(StatusCodes.OK).json({
+ successful: updated > 0
+ })
+ }
+}
+
+/**
+ * Check if conformance data exists in the database
+ *
+ * @param {*} db
+ * @returns boolean value of data exist or not
+ */
+function httpGetConformDataExists(db) {
+ return async (request, response) => {
+ let conformDataExists = await queryFeature.checkIfConformanceDataExist(db)
+ response.status(StatusCodes.OK).json(conformDataExists)
+ }
+}
+
+/**
+ * Set warning for the required element, and delete its existing warning if any.
+ *
+ * @param {*} db
+ * @returns response of setting the warning notification
+ */
+function httpPostRequiredElementWarning(db) {
+ return async (request, response) => {
+ let { element, contextMessage, requiredText, notSupportedText, added } =
+ request.body
+ let resp = await querySessionNotification.setRequiredElementWarning(
+ db,
+ { element, contextMessage, requiredText, notSupportedText, added },
+ request.zapSessionId
+ )
+ response.status(StatusCodes.OK).json(resp)
+ }
+}
+
/**
* duplicate all clusters and attributes of an old endpoint type, using oldEndpointType id and newly created endpointType id
*
@@ -1115,6 +1278,14 @@ exports.post = [
{
uri: restApi.uri.duplicateEndpointType,
callback: httpPostDuplicateEndpointType
+ },
+ {
+ uri: restApi.uri.checkConformOnFeatureUpdate,
+ callback: httpPostCheckConformOnFeatureUpdate
+ },
+ {
+ uri: restApi.uri.requiredElementWarning,
+ callback: httpPostRequiredElementWarning
}
]
@@ -1170,6 +1341,14 @@ exports.get = [
{
uri: restApi.uri.getAllPackages,
callback: httpGetAllPackages
+ },
+ {
+ uri: restApi.uri.conformDataExists,
+ callback: httpGetConformDataExists
+ },
+ {
+ uri: restApi.uri.requiredElements,
+ callback: httpGetRequiredElements
}
]
@@ -1187,3 +1366,10 @@ exports.delete = [
callback: httpDeletePackageNotification
}
]
+
+exports.patch = [
+ {
+ uri: restApi.uri.updateBitOfFeatureMapAttribute,
+ callback: httpPatchUpdateBitOfFeatureMapAttribute
+ }
+]
diff --git a/src-electron/zcl/zcl-loader-silabs.js b/src-electron/zcl/zcl-loader-silabs.js
index 2fe6022982..518ab91c68 100644
--- a/src-electron/zcl/zcl-loader-silabs.js
+++ b/src-electron/zcl/zcl-loader-silabs.js
@@ -492,6 +492,7 @@ function prepareCluster(cluster, context, isExtension = false) {
description: command.description ? command.description[0].trim() : '',
source: command.$.source,
isOptional: command.$.optional == 'true' ? true : false,
+ conformance: parseConformanceFromXML(command),
mustUseTimedInvoke: command.$.mustUseTimedInvoke == 'true',
introducedIn: command.$.introducedIn,
removedIn: command.$.removedIn,
@@ -547,6 +548,7 @@ function prepareCluster(cluster, context, isExtension = false) {
manufacturerCode: event.$.manufacturerCode,
name: event.$.name,
side: event.$.side,
+ conformance: parseConformanceFromXML(event),
priority: event.$.priority,
description: event.description ? event.description[0].trim() : '',
isOptional: event.$.optional == 'true',
@@ -647,6 +649,7 @@ function prepareCluster(cluster, context, isExtension = false) {
: attribute.$.type,
side: attribute.$.side,
define: attribute.$.define,
+ conformance: parseConformanceFromXML(attribute),
min: attribute.$.min,
max: attribute.$.max,
minLength: 0,
@@ -734,7 +737,7 @@ function prepareCluster(cluster, context, isExtension = false) {
bit: feature.$.bit,
defaultValue: feature.$.default,
description: feature.$.summary,
- conformance: parseFeatureConformance(feature)
+ conformance: parseConformanceFromXML(feature)
}
ret.features.push(f)
@@ -1686,10 +1689,9 @@ function prepareDeviceType(deviceType) {
}
if ('features' in include) {
include.features[0].feature.forEach((f) => {
- let conformance = parseFeatureConformance(f)
features.push({
code: f.$.code,
- conformance: conformance
+ conformance: parseConformanceFromXML(f)
})
})
}
@@ -2252,7 +2254,11 @@ async function parseFeatureFlags(db, packageId, featureFlags) {
}
/**
- * Parses feature conformance or an operand in feature conformance recursively from xml data.
+ * Parses conformance from XML data.
+ * The conformance could come from features, attributes, commands, or events
+ *
+ * Call recursive helper function to parse conformance only if the conformance exists.
+ * Otherwise, return empty string directly
*
* An example of parsing the conformance of 'User' device type feature:
*
@@ -2267,7 +2273,7 @@ async function parseFeatureFlags(db, packageId, featureFlags) {
* { "feature": [
* { "$": {"name": "PIN"}},
* { "$": {"name": "RID"}},
- * { "$": {"name": "FPG"}},
+ * { "$": {"name": "FGP"}},
* { "$": {"name": "FACE"}}
* ]
* }
@@ -2278,18 +2284,41 @@ async function parseFeatureFlags(db, packageId, featureFlags) {
* ]
* }
*
- * Output device type feature conformance string:
- * "Matter & (PIN | RID | FPG | FACE)"
+ * Output conformance string:
+ * "Matter & (PIN | RID | FGP | FACE)"
*
- * @param {*} operand - The operand to be parsed.
- * @returns The feature conformance string.
+ * @param {*} operand
+ * @returns The conformance string
*/
-function parseFeatureConformance(operand) {
+function parseConformanceFromXML(operand) {
+ let hasConformance = Object.keys(operand).some((key) =>
+ key.includes('Conform')
+ )
+ return hasConformance ? parseConformanceRecursively(operand) : ''
+}
+
+/**
+ * helper function to parse conformance or an operand in conformance recursively
+ *
+ * The baseLevelTerms variable include terms that can not have nested terms.
+ * When they appear, stop recursing and return the name inside directly
+ *
+ * @param {*} operand
+ * @param {*} depth
+ * @param {*} parentJoinChar
+ * @returns The conformance string.
+ */
+function parseConformanceRecursively(operand, depth = 0, parentJoinChar = '') {
+ if (depth > 200) {
+ throw new Error(`Maximum recursion depth exceeded
+ when parsing conformance: ${JSON.stringify(operand)}`)
+ }
+ const baseLevelTerms = ['feature', 'condition', 'attribute', 'command']
if (operand.mandatoryConform) {
let insideTerm = operand.mandatoryConform[0]
// Recurse further if insideTerm is not empty
if (insideTerm && Object.keys(insideTerm).toString() != '$') {
- return parseFeatureConformance(operand.mandatoryConform[0])
+ return parseConformanceRecursively(operand.mandatoryConform[0], depth + 1)
} else {
return 'M'
}
@@ -2298,65 +2327,64 @@ function parseFeatureConformance(operand) {
// check '$' key is not the only key in the object to handle special cases
// e.g. ' '
if (insideTerm && Object.keys(insideTerm).toString() != '$') {
- return `[${parseFeatureConformance(operand.optionalConform[0])}]`
+ return `[${parseConformanceRecursively(operand.optionalConform[0], depth + 1)}]`
} else {
return 'O'
}
+ } else if (operand.otherwiseConform) {
+ return Object.entries(operand.otherwiseConform[0])
+ .map(([key, value]) =>
+ parseConformanceRecursively({ [key]: value }, depth + 1)
+ )
+ .join(', ')
+ } else if (operand.notTerm) {
+ // need to surround terms inside a notTerm with '()' if it contains multiple terms
+ // e.g. !(A | B) or !(A & B)
+ // able to process multiple parallel notTerms, e.g. !A & !B
+ return operand.notTerm
+ .map((term) => {
+ let nt = parseConformanceRecursively(term, depth + 1)
+ return nt.includes('&') || nt.includes('|') ? `!(${nt})` : `!${nt}`
+ })
+ .join(` ${parentJoinChar} `)
+ } else if (operand.andTerm || operand.orTerm) {
+ // process andTerm and orTerm in the same logic
+ // when joining multiple orTerms inside andTerms, we need to
+ // surround them with '()', vice versa for andTerms inside orTerms
+ // e.g. A & (B | C) or A | (B & C)
+ let joinChar = operand.andTerm ? '&' : '|'
+ let termKey = operand.andTerm ? 'andTerm' : 'orTerm'
+ let oppositeChar = joinChar == '&' ? '|' : '&'
+ return Object.entries(operand[termKey][0])
+ .map(([key, value]) => {
+ if (baseLevelTerms.includes(key)) {
+ return value.map((operand) => operand.$.name).join(` ${joinChar} `)
+ } else {
+ let terms = parseConformanceRecursively(
+ { [key]: value },
+ depth + 1,
+ joinChar
+ )
+ return terms.includes(oppositeChar) ? `(${terms})` : terms
+ }
+ })
+ .join(` ${joinChar} `)
} else if (operand.provisionalConform) {
return 'P'
} else if (operand.disallowConform) {
return 'X'
} else if (operand.deprecateConform) {
return 'D'
- } else if (operand.feature) {
- return operand.feature[0].$.name
- } else if (operand.condition) {
- return operand.condition[0].$.name
- } else if (operand.otherwiseConform) {
- return Object.entries(operand.otherwiseConform[0])
- .map(([key, value]) => parseFeatureConformance({ [key]: value }))
- .join(', ')
- } else if (operand.notTerm) {
- let notTerms = parseFeatureConformance(operand.notTerm[0])
- // need to surround notTerms with '()' if it contains multiple terms
- // e.g. !(A | B) or !(A & B)
- return notTerms.includes('&') || notTerms.includes('|')
- ? `!(${notTerms})`
- : `!${notTerms}`
- } else if (operand.andTerm) {
- return parseAndOrConformanceTerms(operand.andTerm, '&')
- } else if (operand.orTerm) {
- return parseAndOrConformanceTerms(operand.orTerm, '|')
} else {
- return ''
- }
-}
-
-/**
- * Helper function to parse andTerm or orTerm from xml data
- * @param {*} operand
- * @param {*} joinChar
- * @returns feature conformance string
- */
-function parseAndOrConformanceTerms(operand, joinChar) {
- // when joining multiple orTerms inside andTerms, we need to
- // surround them with '()', vice versa for andTerms inside orTerms
- // e.g. A & (B | C) or A | (B & C)
- let oppositeChar = joinChar === '&' ? '|' : '&'
- let oppositeTerm = joinChar === '&' ? 'orTerm' : 'andTerm'
-
- return Object.entries(operand[0])
- .map(([key, value]) => {
- if (key == 'feature' || key == 'condition') {
- return value.map((operand) => operand.$.name).join(` ${joinChar} `)
- } else if (key == oppositeTerm) {
- let terms = parseFeatureConformance({ [key]: value })
- return terms.includes(oppositeChar) ? `(${terms})` : terms
- } else {
- return ''
+ // reach base level terms, return the name directly
+ for (const term of baseLevelTerms) {
+ if (operand[term]) {
+ return operand[term][0].$.name
}
- })
- .join(` ${joinChar} `)
+ }
+ // reaching here means the term is too complex to parse
+ return 'desc'
+ }
}
/**
diff --git a/src-shared/db-enum.js b/src-shared/db-enum.js
index 4e9a9ccc53..eb70e43f79 100644
--- a/src-shared/db-enum.js
+++ b/src-shared/db-enum.js
@@ -220,6 +220,7 @@ exports.packageMatch = {
exports.deviceTypeFeature = {
name: {
+ enabled: 'enabled',
deviceType: 'deviceType',
cluster: 'cluster',
clusterSide: 'clusterSide',
@@ -230,6 +231,7 @@ exports.deviceTypeFeature = {
description: 'description'
},
label: {
+ enabled: 'Enabled',
deviceType: 'Device Type',
cluster: 'Cluster',
clusterSide: 'Cluster Side',
diff --git a/src-shared/rest-api.js b/src-shared/rest-api.js
index ed76449be4..73308107d0 100644
--- a/src-shared/rest-api.js
+++ b/src-shared/rest-api.js
@@ -36,11 +36,16 @@ const uri = {
packageNotification: '/packageNotification',
packageNotificationById: '/packageNotificationById/:packageId',
updateNotificationToSeen: '/updateNotificationToSeen',
+ updateBitOfFeatureMapAttribute: '/updateBitOfFeatureMapAttribute',
+ conformDataExists: '/conformDataExists',
+ requiredElementWarning: '/requiredElementWarning',
deleteSessionNotification: '/deleteSessionNotification',
deletePackageNotification: 'deletePackageNotification',
duplicateEndpoint: '/duplicateEndpoint',
duplicateEndpointType: '/duplicateEndpointType',
dirtyFlag: '/dirtyFlag',
+ checkConformOnFeatureUpdate: '/checkConformOnFeatureUpdate',
+ requiredElements: '/requiredElements',
option: '/option',
uiOptions: '/uiOptions',
commandUpdate: '/command/update',
diff --git a/src/components/ZclAttributeManager.vue b/src/components/ZclAttributeManager.vue
index d1eb518389..94d324a8aa 100644
--- a/src/components/ZclAttributeManager.vue
+++ b/src/components/ZclAttributeManager.vue
@@ -44,19 +44,23 @@ limitations under the License.
style="width: 30px; max-width: 30px"
>
- This attribute is mandatory for the cluster and device type
- configuration you have enabled
+
+ {{ warning }}
+
@@ -294,15 +298,52 @@ export default {
setToNull(row, selectedClusterId) {
this.handleLocalChange(null, 'defaultValue', row, selectedClusterId)
},
- isAttributeRequired(attribute) {
- return this.requiredAttributes.includes(attribute.id)
+ isAttributeRequired(attributeId) {
+ return this.requiredAttributes.includes(attributeId)
},
- displayAttrWarning(row) {
+ isRequiredAttributeDisabled(attributeId) {
return (
- this.isAttributeRequired(row) &&
- !this.selection.includes(
- this.hashAttributeIdClusterId(row.id, this.selectedCluster.id)
- )
+ this.isAttributeRequired(attributeId) &&
+ !this.isAttributeSelected(attributeId)
+ )
+ },
+ /* Display warnings if attributes required by device type is disabled,
+ or if attribute state does not match mandatory or notSupported conformance.
+ Two types of warnings can be displayed at the same time. */
+ displayAttrWarning(attributeId) {
+ return (
+ (this.enableFeature &&
+ ((this.attributesRequiredByConform[attributeId] &&
+ !this.isAttributeSelected(attributeId)) ||
+ (this.attributesNotSupportedByConform[attributeId] &&
+ this.isAttributeSelected(attributeId)))) ||
+ this.isRequiredAttributeDisabled(attributeId)
+ )
+ },
+ getAttrWarning(attributeId) {
+ let warnings = []
+ if (
+ this.attributesRequiredByConform[attributeId] &&
+ !this.isAttributeSelected(attributeId) &&
+ this.enableFeature
+ ) {
+ warnings.push(this.attributesRequiredByConform[attributeId])
+ }
+ if (
+ this.attributesNotSupportedByConform[attributeId] &&
+ this.isAttributeSelected(attributeId) &&
+ this.enableFeature
+ ) {
+ warnings.push(this.attributesNotSupportedByConform[attributeId])
+ }
+ if (this.isRequiredAttributeDisabled(attributeId)) {
+ warnings.push(this.defaultWarning)
+ }
+ return warnings
+ },
+ isAttributeSelected(attributeId) {
+ return this.selection.includes(
+ this.hashAttributeIdClusterId(attributeId, this.selectedCluster.id)
)
},
customAttributeSort(rows, sortBy, descending) {
@@ -415,10 +456,13 @@ export default {
sortBy: 'clientServer'
},
columns: [],
- forcedExternal: []
+ forcedExternal: [],
+ defaultWarning: `This attribute is mandatory for the
+ cluster and device type configuration you have enabled`
}
},
mounted() {
+ this.setRequiredConformElement()
this.columns = [
{
name: 'status',
diff --git a/src/components/ZclClusterManager.vue b/src/components/ZclClusterManager.vue
index 2179e3bf09..7ea46d3c23 100644
--- a/src/components/ZclClusterManager.vue
+++ b/src/components/ZclClusterManager.vue
@@ -46,7 +46,7 @@ limitations under the License.
rounded
label="Device Type Features"
color="secondary"
- @click="updateDeviceTypeFeatures"
+ @click="setDeviceTypeFeatures"
to="/feature"
/>
@@ -151,6 +151,7 @@ export default {
this.scrollToElementById(this.lastSelectedDomain)
}
this.changeDomainFilter(this.filter)
+ this.$store.dispatch('zap/updateConformDataExists')
},
watch: {
enabledClusters() {
@@ -350,13 +351,12 @@ export default {
changeFilterString(filterString) {
this.$store.dispatch('zap/setFilterString', filterString)
},
- updateDeviceTypeFeatures() {
- let deviceTypeRefs =
- this.endpointDeviceTypeRef[this.selectedEndpointTypeId]
- this.$store.dispatch(
- 'zap/updateSelectedDeviceTypeFeatures',
- deviceTypeRefs
- )
+ setDeviceTypeFeatures() {
+ let deviceTypeRefs = this.endpointDeviceTypeRef[this.selectedEndpointId]
+ this.$store.dispatch('zap/setDeviceTypeFeatures', {
+ deviceTypeRefs: deviceTypeRefs,
+ endpointTypeRef: this.selectedEndpointId
+ })
}
},
components: {
diff --git a/src/components/ZclCommandManager.vue b/src/components/ZclCommandManager.vue
index ed996aca81..e1d783ff44 100644
--- a/src/components/ZclCommandManager.vue
+++ b/src/components/ZclCommandManager.vue
@@ -48,7 +48,12 @@ limitations under the License.
self="bottom middle"
:offset="[10, 10]"
>
- {{ validationErrorMessage }}
+
+ {{ warning }}
+
@@ -135,10 +140,12 @@ limitations under the License.