Skip to content

Commit fa3a845

Browse files
committed
Adding features in cluster xml as a bitmap such that bitmap name='feature' can be removed from the xml in favor of features which holds the featuremap information as well as defines the feature bitmap such that there is no duplicate information between features and bitmap name=feature
JIRA: ZAPP-1346
1 parent ec701ac commit fa3a845

File tree

3 files changed

+123
-17
lines changed

3 files changed

+123
-17
lines changed

apack.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Graphical configuration tool for application and libraries based on Zigbee Cluster Library.",
55
"path": [".", "node_modules/.bin/", "ZAP.app/Contents/MacOS"],
66
"requiredFeatureLevel": "apack.core:9",
7-
"featureLevel": 101,
7+
"featureLevel": 102,
88
"uc.triggerExtension": "zap",
99
"executable": {
1010
"zap:win32.x86_64": {

src-electron/zcl/zcl-loader-silabs.js

+94-16
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,11 @@ function prepareDataType(a, dataType, typeMap) {
10121012
id: parseInt(a.$.id),
10131013
description: a.$.description ? a.$.description : a.$.name,
10141014
discriminator_ref: dataType ? dataType : dataTypeRef,
1015-
cluster_code: a.cluster ? a.cluster : null,
1015+
cluster_code: a.cluster
1016+
? a.cluster
1017+
: a.$.cluster_code
1018+
? [{ $: { code: a.$.cluster_code[0] } }]
1019+
: null, // else case: Treating features in a cluster as a bitmap
10161020
}
10171021
}
10181022

@@ -1274,7 +1278,11 @@ function prepareEnumOrBitmap(db, packageId, a, dataType, typeMap) {
12741278
return {
12751279
name: a.$.name,
12761280
type: a.$.type.toLowerCase(),
1277-
cluster_code: a.cluster ? a.cluster : null,
1281+
cluster_code: a.cluster
1282+
? a.cluster
1283+
: a.$.cluster_code
1284+
? [{ $: { code: a.$.cluster_code[0] } }]
1285+
: null, // else case: Treating features in a cluster as a bitmap
12781286
discriminator_ref: dataType,
12791287
}
12801288
}
@@ -1420,21 +1428,40 @@ async function processBitmapFields(
14201428
env.logDebug(`${filePath}, ${packageId}: ${data.length} Bitmap Fields.`)
14211429
let bitmapFields = []
14221430
let lastFieldId = -1
1423-
data.forEach((bm) => {
1424-
if ('field' in bm) {
1425-
bm.field.forEach((item) => {
1426-
let defaultFieldId = lastFieldId + 1
1427-
lastFieldId = item.$.fieldId ? parseInt(item.$.fieldId) : defaultFieldId
1428-
bitmapFields.push({
1429-
bitmapName: bm.$.name,
1430-
bitmapClusterCode: bm.cluster ? bm.cluster : null,
1431-
name: item.$.name,
1432-
mask: parseInt(item.$.mask),
1433-
fieldIdentifier: lastFieldId,
1431+
if (!('features' in data)) {
1432+
data.forEach((bm) => {
1433+
if ('field' in bm) {
1434+
bm.field.forEach((item) => {
1435+
let defaultFieldId = lastFieldId + 1
1436+
lastFieldId = item.$.fieldId
1437+
? parseInt(item.$.fieldId)
1438+
: defaultFieldId
1439+
bitmapFields.push({
1440+
bitmapName: bm.$.name,
1441+
bitmapClusterCode: bm.cluster ? bm.cluster : null,
1442+
name: item.$.name,
1443+
mask: parseInt(item.$.mask),
1444+
fieldIdentifier: lastFieldId,
1445+
})
14341446
})
1447+
}
1448+
})
1449+
// Treating features in a cluster as a bitmap
1450+
} else if (
1451+
'features' in data &&
1452+
data.features.length == 1 &&
1453+
'feature' in data.features[0]
1454+
) {
1455+
data.features[0].feature.forEach((item) => {
1456+
bitmapFields.push({
1457+
bitmapName: 'Feature',
1458+
bitmapClusterCode: [{ $: { code: data.code[0] } }],
1459+
name: item.$.name,
1460+
mask: 1 << item.$.bit,
1461+
fieldIdentifier: item.$.bit,
14351462
})
1436-
}
1437-
})
1463+
})
1464+
}
14381465
return queryLoader.insertBitmapFields(
14391466
db,
14401467
packageId,
@@ -1577,7 +1604,7 @@ function prepareDeviceType(deviceType) {
15771604
if ('features' in include) {
15781605
include.features[0].feature.forEach((f) => {
15791606
// Only adding madatory features for now
1580-
if (f.mandatoryConform[0] === '') {
1607+
if (f.mandatoryConform && f.mandatoryConform[0] === '') {
15811608
features.push(f.$.name)
15821609
}
15831610
})
@@ -1637,6 +1664,7 @@ async function processParsedZclData(
16371664
let packageId = argument.packageId
16381665
previouslyKnownPackages.add(packageId)
16391666
let knownPackages = Array.from(previouslyKnownPackages)
1667+
let featureClusters = []
16401668

16411669
if (!('result' in argument)) {
16421670
return []
@@ -1685,6 +1713,7 @@ async function processParsedZclData(
16851713
)
16861714
}
16871715
if ('cluster' in toplevel) {
1716+
featureClusters = toplevel.cluster.filter((c) => 'features' in c)
16881717
batch2.push(
16891718
processClusters(db, filePath, packageId, toplevel.cluster, context)
16901719
)
@@ -1717,6 +1746,31 @@ async function processParsedZclData(
17171746
)
17181747
)
17191748
}
1749+
1750+
// Treating features in a cluster as a bitmap
1751+
if (featureClusters.length > 0) {
1752+
featureClusters.forEach((fc) => {
1753+
batch3.push(
1754+
processDataType(
1755+
db,
1756+
filePath,
1757+
packageId,
1758+
knownPackages,
1759+
[
1760+
{
1761+
$: {
1762+
name: 'Feature',
1763+
type: 'BITMAP32',
1764+
cluster_code: [fc.code[0]],
1765+
},
1766+
},
1767+
],
1768+
dbEnum.zclType.bitmap
1769+
)
1770+
)
1771+
})
1772+
}
1773+
17201774
if (dbEnum.zclType.enum in toplevel) {
17211775
batch3.push(
17221776
processDataType(
@@ -1785,6 +1839,22 @@ async function processParsedZclData(
17851839
processBitmap(db, filePath, packageId, knownPackages, toplevel.bitmap)
17861840
)
17871841
}
1842+
// Treating features in a cluster as a bitmap
1843+
if (featureClusters.length > 0) {
1844+
featureClusters.forEach((fc) => {
1845+
Batch5.push(
1846+
processBitmap(db, filePath, packageId, knownPackages, [
1847+
{
1848+
$: {
1849+
name: 'Feature',
1850+
type: 'BITMAP32',
1851+
cluster_code: [fc.code[0]],
1852+
},
1853+
},
1854+
])
1855+
)
1856+
})
1857+
}
17881858
if (dbEnum.zclType.struct in toplevel) {
17891859
Batch5.push(
17901860
processStruct(db, filePath, packageId, knownPackages, toplevel.struct)
@@ -1810,6 +1880,14 @@ async function processParsedZclData(
18101880
)
18111881
)
18121882
}
1883+
// Treating features in a cluster as a bitmap
1884+
if (featureClusters.length > 0) {
1885+
featureClusters.forEach((fc) => {
1886+
batch6.push(
1887+
processBitmapFields(db, filePath, packageId, knownPackages, fc)
1888+
)
1889+
})
1890+
}
18131891
if (dbEnum.zclType.struct in toplevel) {
18141892
batch6.push(
18151893
processStructItems(

test/gen-matter-1.test.js

+28
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,34 @@ test('Validate loading', async () => {
7979
expect(cluster.name).toBe('OTA Software Update Provider')
8080
})
8181

82+
test('Validate loading of features as bitmap', async () => {
83+
/* See level-control-cluster.xml which has the following:
84+
<features>
85+
<feature bit="0" code="OO" name="OnOff" default="1" summary="Dependency with the On/Off cluster">
86+
<optionalConform/>
87+
</feature>
88+
<feature bit="1" code="LT" name="Lighting" default="0" summary="Behavior that supports lighting applications">
89+
<optionalConform/>
90+
</feature>
91+
<feature bit="2" code="FQ" name="Frequency" default="0" summary="Supports frequency attributes and behavior.
92+
The Pulse Width Modulation cluster was created
93+
for frequency control.">
94+
<provisionalConform/>
95+
</feature>
96+
</features>
97+
*/
98+
let clusterInfo = await queryZcl.selectClusterByCode(db, zclPackageId, 0x0008)
99+
100+
let dataType = await queryZcl.selectDataTypeByNameAndClusterId(
101+
db,
102+
'Feature',
103+
clusterInfo.id,
104+
[zclPackageId]
105+
)
106+
expect(dataType).not.toBeNull()
107+
expect(dataType.name).toEqual('Feature')
108+
})
109+
82110
test(
83111
'Basic gen template parsing and generation',
84112
async () => {

0 commit comments

Comments
 (0)