Skip to content

Commit be9048b

Browse files
authored
Set feature conformance warnings on ZAP file import and Replace outdated equivalents (#1525)
* add feature warning on import and adjust unit tests
1 parent 7b977aa commit be9048b

File tree

10 files changed

+152
-272
lines changed

10 files changed

+152
-272
lines changed

docs/api.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3651,7 +3651,7 @@ This module provides queries for features.
36513651
* [~checkMissingTerms(expression, elementMap)](#module_DB API_ feature related queries..checkMissingTerms) ⇒
36523652
* [~filterElementsContainingDesc(elements)](#module_DB API_ feature related queries..filterElementsContainingDesc) ⇒
36533653
* [~filterRelatedDescElements(elements, featureCode)](#module_DB API_ feature related queries..filterRelatedDescElements) ⇒
3654-
* [~generateWarningMessage(featureData, endpointId, missingTerms, featureMap, descElements)](#module_DB API_ feature related queries..generateWarningMessage) ⇒
3654+
* [~generateWarningMessage(featureData, endpointId, elementMap, featureMap, descElements)](#module_DB API_ feature related queries..generateWarningMessage) ⇒
36553655
* [~checkElementConformance(elements, featureMap, featureData, endpointId)](#module_DB API_ feature related queries..checkElementConformance) ⇒
36563656
* [~filterElementsToUpdate(elements, elementMap, featureCode)](#module_DB API_ feature related queries..filterElementsToUpdate) ⇒
36573657
* [~getOutdatedElementWarning(featureData, elements, elementMap)](#module_DB API_ feature related queries..getOutdatedElementWarning) ⇒
@@ -3762,9 +3762,9 @@ Filter an array of elements by if any element has conformance containing the ter
37623762

37633763
<a name="module_DB API_ feature related queries..generateWarningMessage"></a>
37643764

3765-
### DB API: feature related queries~generateWarningMessage(featureData, endpointId, missingTerms, featureMap, descElements) ⇒
3765+
### DB API: feature related queries~generateWarningMessage(featureData, endpointId, elementMap, featureMap, descElements) ⇒
37663766
Generate a warning message after processing conformance of the updated device type feature.
3767-
Set flags to decide whether to show a popup warning or disable changes in the frontend.
3767+
Set flags to decide whether to show warnings or disable changes in the frontend.
37683768

37693769
**Kind**: inner method of [<code>DB API: feature related queries</code>](#module_DB API_ feature related queries)
37703770
**Returns**: warning message array, disableChange flag, and displayWarning flag
@@ -3773,7 +3773,7 @@ Set flags to decide whether to show a popup warning or disable changes in the fr
37733773
| --- | --- |
37743774
| featureData | <code>\*</code> |
37753775
| endpointId | <code>\*</code> |
3776-
| missingTerms | <code>\*</code> |
3776+
| elementMap | <code>\*</code> |
37773777
| featureMap | <code>\*</code> |
37783778
| descElements | <code>\*</code> |
37793779

src-electron/db/query-feature.js

Lines changed: 56 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,28 @@ async function getFeaturesByDeviceTypeRefs(
114114
`,
115115
arg
116116
)
117-
return features.map(dbMapping.map.deviceTypeFeature)
117+
let deviceTypeFeatures = features.map(dbMapping.map.deviceTypeFeature)
118+
119+
/* For a device type feature under the same endpoint and cluster, but different device types,
120+
merge their rows into one and combine their device type names into a list. */
121+
let result = []
122+
deviceTypeFeatures.forEach((row) => {
123+
const key = `${row.endpointTypeClusterId}-${row.featureId}`
124+
if (key in result) {
125+
let existingRow = result[key]
126+
if (!existingRow.deviceTypes.includes(row.deviceType)) {
127+
existingRow.deviceTypes.push(row.deviceType)
128+
}
129+
} else {
130+
result[key] = {
131+
...row,
132+
deviceTypes: [row.deviceType]
133+
}
134+
delete result[key].deviceType
135+
}
136+
})
137+
138+
return Object.values(result)
118139
}
119140

120141
/**
@@ -258,21 +279,21 @@ function filterRelatedDescElements(elements, featureCode) {
258279

259280
/**
260281
* Generate a warning message after processing conformance of the updated device type feature.
261-
* Set flags to decide whether to show a popup warning or disable changes in the frontend.
282+
* Set flags to decide whether to show warnings or disable changes in the frontend.
262283
*
263284
* @param {*} featureData
264285
* @param {*} endpointId
265-
* @param {*} missingTerms
286+
* @param {*} elementMap
266287
* @param {*} featureMap
267288
* @param {*} descElements
268289
* @returns warning message array, disableChange flag, and displayWarning flag
269290
*/
270291
function generateWarningMessage(
271292
featureData,
272293
endpointId,
273-
missingTerms,
274294
featureMap,
275-
descElements
295+
elementMap = {},
296+
descElements = {}
276297
) {
277298
let featureName = featureData.name
278299
let added = featureMap[featureData.code] ? true : false
@@ -284,17 +305,22 @@ function generateWarningMessage(
284305
}
285306
result.warningMessage = []
286307

287-
if (missingTerms.length > 0) {
288-
let missingTermsString = missingTerms.join(', ')
289-
result.warningMessage.push(
290-
'On Endpoint ' +
291-
endpointId +
292-
', feature ' +
293-
featureName +
294-
' cannot be enabled as its conformance depends on non device type features ' +
295-
missingTermsString +
296-
' with unknown values'
297-
)
308+
let warningPrefix =
309+
`⚠ Check Feature Compliance on endpoint: ${endpointId}, cluster: ${featureData.cluster}, ` +
310+
`feature: ${featureName} (bit ${featureData.bit} in featureMap attribute)`
311+
312+
let missingTerms = []
313+
if (Object.keys(elementMap).length > 0) {
314+
missingTerms = checkMissingTerms(featureData.conformance, elementMap)
315+
if (missingTerms.length > 0) {
316+
let missingTermsString = missingTerms.join(', ')
317+
result.warningMessage.push(
318+
warningPrefix +
319+
' cannot be enabled as its conformance depends on non device type features ' +
320+
missingTermsString +
321+
' with unknown values'
322+
)
323+
}
298324
}
299325

300326
if (
@@ -310,10 +336,7 @@ function generateWarningMessage(
310336
.join(', ')
311337
let eventNames = descElements.events.map((event) => event.name).join(', ')
312338
result.warningMessage.push(
313-
'On endpoint ' +
314-
endpointId +
315-
', feature ' +
316-
featureName +
339+
warningPrefix +
317340
' cannot be enabled as ' +
318341
(attributeNames ? 'attribute ' + attributeNames : '') +
319342
(attributeNames && commandNames ? ', ' : '') +
@@ -326,46 +349,38 @@ function generateWarningMessage(
326349

327350
if (
328351
missingTerms.length == 0 &&
329-
descElements.attributes.length == 0 &&
330-
descElements.commands.length == 0 &&
331-
descElements.events.length == 0
352+
(Object.keys(descElements).length == 0 ||
353+
(descElements.attributes.length == 0 &&
354+
descElements.commands.length == 0 &&
355+
descElements.events.length == 0))
332356
) {
333357
let conformance = evaluateConformanceExpression(
334358
featureData.conformance,
335359
featureMap
336360
)
337-
// change is not disabled, by default does not display warning
361+
// if no missing terms and no desc elements, enable the feature change
338362
result.disableChange = false
339363
result.displayWarning = false
340364
// in this case only 1 warning message is needed
341365
result.warningMessage = ''
342366
if (conformance == 'notSupported') {
343367
result.warningMessage =
344-
'On endpoint ' +
345-
endpointId +
346-
', feature ' +
347-
featureName +
348-
' is enabled, but it is not supported for device type ' +
368+
warningPrefix +
369+
' should be disabled, as it is not supported for device type: ' +
349370
deviceTypeNames
350371
result.displayWarning = added
351372
}
352373
if (conformance == 'provisional') {
353374
result.warningMessage =
354-
'On endpoint ' +
355-
endpointId +
356-
', feature ' +
357-
featureName +
358-
' is enabled, but it is still provisional for device type ' +
375+
warningPrefix +
376+
' is enabled, but it is still provisional for device type: ' +
359377
deviceTypeNames
360378
result.displayWarning = added
361379
}
362380
if (conformance == 'mandatory') {
363381
result.warningMessage =
364-
'On endpoint ' +
365-
endpointId +
366-
', feature ' +
367-
featureName +
368-
' is disabled, but it is mandatory for device type ' +
382+
warningPrefix +
383+
' should be enabled, as it is mandatory for device type: ' +
369384
deviceTypeNames
370385
result.displayWarning = !added
371386
}
@@ -416,12 +431,11 @@ function checkElementConformance(
416431
descElements.commands = filterRelatedDescElements(commands, featureCode)
417432
descElements.events = filterRelatedDescElements(events, featureCode)
418433

419-
let missingTerms = checkMissingTerms(featureData.conformance, elementMap)
420434
warningInfo = generateWarningMessage(
421435
featureData,
422436
endpointId,
423-
missingTerms,
424437
featureMap,
438+
elementMap,
425439
descElements
426440
)
427441

@@ -675,6 +689,7 @@ async function getEndpointTypeElements(
675689

676690
exports.getFeaturesByDeviceTypeRefs = getFeaturesByDeviceTypeRefs
677691
exports.checkElementConformance = checkElementConformance
692+
exports.generateWarningMessage = generateWarningMessage
678693
exports.evaluateConformanceExpression = evaluateConformanceExpression
679694
exports.filterElementsContainingDesc = filterElementsContainingDesc
680695
exports.filterRelatedDescElements = filterRelatedDescElements

0 commit comments

Comments
 (0)