@@ -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 */
270291function 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
676690exports . getFeaturesByDeviceTypeRefs = getFeaturesByDeviceTypeRefs
677691exports . checkElementConformance = checkElementConformance
692+ exports . generateWarningMessage = generateWarningMessage
678693exports . evaluateConformanceExpression = evaluateConformanceExpression
679694exports . filterElementsContainingDesc = filterElementsContainingDesc
680695exports . filterRelatedDescElements = filterRelatedDescElements
0 commit comments