From bca3a8eac4a6bb7a5ecf6e5947afebaa0f912f06 Mon Sep 17 00:00:00 2001 From: Evgeni Margolis Date: Wed, 18 Jan 2023 13:00:19 -0800 Subject: [PATCH] DRAFT: WIP Support EventList for Matter --- cypress/matterFixtures/data.json | 2 +- src-electron/db/query-endpoint.js | 46 +++++++++++++++++++ .../generator/helper-endpointconfig.js | 41 ++++++++++++++++- .../app/zap-templates/templates/app/helper.js | 33 +++++++++++++ .../zap-templates/templates/chip/helper.js | 2 +- src-electron/util/zcl-util.js | 18 ++++++++ test/gen-template/matter/endpoint-config.zapt | 7 +++ test/test-util.js | 2 +- zcl-builtin/matter/global-attributes.xml | 3 +- 9 files changed, 148 insertions(+), 6 deletions(-) diff --git a/cypress/matterFixtures/data.json b/cypress/matterFixtures/data.json index b9bc252257..dfd379f3de 100644 --- a/cypress/matterFixtures/data.json +++ b/cypress/matterFixtures/data.json @@ -25,7 +25,7 @@ "server2": "Client & Server", "previewBtnData": "access.out", "outOfRangeAmount1": "9999999999999999", - "availableAttributes1": "28", + "availableAttributes1": "32", "availableClusters1": "5", "enum8inputpath": "2", "int16inputpath": "1", diff --git a/src-electron/db/query-endpoint.js b/src-electron/db/query-endpoint.js index 613a7844e5..b3e7a15a74 100644 --- a/src-electron/db/query-endpoint.js +++ b/src-electron/db/query-endpoint.js @@ -265,6 +265,51 @@ ORDER BY C.CODE }) } +/** + * Retrieves endpoint cluster events. + * + * @param {*} db + * @param {*} clusterId + * @param {*} endpointTypeId + * @returns promise that resolves into endpoint cluster events + */ +async function selectEndpointClusterEvents(db, clusterId, endpointTypeId) { + let rows = await dbApi.dbAll( + db, + ` +SELECT + E.EVENT_ID, + E.NAME, + E.CODE, + E.MANUFACTURER_CODE, + E.IS_OPTIONAL +FROM + EVENT AS E +LEFT JOIN + ENDPOINT_TYPE_EVENT AS ETE +ON + E.EVENT_ID = ETE.EVENT_REF +WHERE + E.CLUSTER_REF = ? + AND ETE.ENDPOINT_TYPE_REF = ? +ORDER BY E.MANUFACTURER_CODE, E.CODE + `, + [clusterId, endpointTypeId] + ) + + return rows.map((row) => { + return { + id: row['EVENT_ID'], + name: row['NAME'], + code: row['CODE'], + clusterId: clusterId, + manufacturerCode: row['MANUFACTURER_CODE'], + isOptional: dbApi.fromDbBool(row['IS_OPTIONAL']), + hexCode: '0x' + bin.int16ToHex(row['CODE']), + } + }) +} + /** * Deletes an endpoint. * @@ -379,6 +424,7 @@ WHERE exports.selectEndpointClusters = selectEndpointClusters exports.selectEndpointClusterAttributes = selectEndpointClusterAttributes exports.selectEndpointClusterCommands = selectEndpointClusterCommands +exports.selectEndpointClusterEvents = selectEndpointClusterEvents exports.insertEndpoint = insertEndpoint exports.deleteEndpoint = deleteEndpoint exports.selectEndpoint = selectEndpoint diff --git a/src-electron/generator/helper-endpointconfig.js b/src-electron/generator/helper-endpointconfig.js index 034fdb0d17..22556afd0d 100644 --- a/src-electron/generator/helper-endpointconfig.js +++ b/src-electron/generator/helper-endpointconfig.js @@ -513,10 +513,12 @@ async function collectAttributes(endpointTypes, options) { let commandMfgCodes = [] // Array of { index, mfgCode } objects let clusterMfgCodes = [] // Array of { index, mfgCode } objects let attributeMfgCodes = [] // Array of { index, mfgCode } objects + let eventMfgCodes = [] // Array of { index, mfgCode } objects + let eventList = [] let attributeList = [] let commandList = [] let endpointList = [] // Array of { clusterIndex, clusterCount, attributeSize } - let clusterList = [] // Array of { clusterId, attributeIndex, attributeCount, attributeSize, mask, functions, comment } + let clusterList = [] // Array of { clusterId, attributeIndex, attributeCount, attributeSize, eventIndex, eventCount, mask, functions, comment } let longDefaults = [] // Array of strings representing bytes let longDefaultsIndex = 0 let minMaxIndex = 0 @@ -531,6 +533,7 @@ async function collectAttributes(endpointTypes, options) { let reportList = [] // Array of { direction, endpoint, clusterId, attributeId, mask, mfgCode, minOrSource, maxOrEndpoint, reportableChangeOrTimeout } let longDefaultsList = [] // Array of { value, size. comment } let attributeIndex = 0 + let eventIndex = 0 let spaceForDefaultValue = options.spaceForDefaultValue !== undefined ? options.spaceForDefaultValue @@ -563,6 +566,8 @@ async function collectAttributes(endpointTypes, options) { attributeIndex: attributeIndex, attributeCount: c.attributes.length, attributeSize: 0, + eventIndex: eventIndex, + eventCount: c.events.length, mask: [], commands: [], functions: 'NULL', @@ -573,6 +578,7 @@ async function collectAttributes(endpointTypes, options) { clusterIndex++ attributeIndex += c.attributes.length + eventIndex += c.events.length c.attributes.sort(zclUtil.attributeComparator) @@ -850,6 +856,27 @@ async function collectAttributes(endpointTypes, options) { commandMfgCodes.push(mfgCmd) } }) + + // Go over the events + c.events.sort(zclUtil.eventComparator) + + c.events.forEach((ev) => { + let event = { + eventId: asMEI(ev.manufacturerCode, ev.code), + name: ev.name, + comment: cluster.comment, + } + eventList.push(event) + + if (ev.manufacturerCode) { + let mfgEv = { + index: eventList.length - 1, + mfgCode: ev.manufacturerCode, + } + eventMfgCodes.push(mfgEv) + } + }) + endpointAttributeSize += clusterAttributeSize cluster.attributeSize = clusterAttributeSize clusterList.push(cluster) @@ -871,7 +898,9 @@ async function collectAttributes(endpointTypes, options) { clusterList: clusterList, attributeList: attributeList, commandList: commandList, + eventList: eventList, longDefaults: longDefaults, + eventMfgCodes: eventMfgCodes, clusterMfgCodes: clusterMfgCodes, commandMfgCodes: commandMfgCodes, attributeMfgCodes: attributeMfgCodes, @@ -1011,11 +1040,12 @@ function endpoint_config(options) { ept.clusters = clusters // Put 'clusters' into endpoint let ps = [] clusters.forEach((cl) => { - // No client-side attributes or commands (at least for + // No client-side attributes, commands, and events (at least for // endpoint_config purposes) in Matter. if (cl.side == dbEnum.side.client) { cl.attributes = [] cl.commands = [] + cl.events = [] return } ps.push( @@ -1042,6 +1072,13 @@ function endpoint_config(options) { cl.commands = commands }) ) + ps.push( + queryEndpoint + .selectEndpointClusterEvents(db, cl.clusterId, ept.id) + .then((events) => { + cl.events = events + }) + ) }) return Promise.all(ps) }) diff --git a/src-electron/generator/matter/app/zap-templates/templates/app/helper.js b/src-electron/generator/matter/app/zap-templates/templates/app/helper.js index 6a25288469..bc140f62dd 100644 --- a/src-electron/generator/matter/app/zap-templates/templates/app/helper.js +++ b/src-electron/generator/matter/app/zap-templates/templates/app/helper.js @@ -38,6 +38,7 @@ const TestHelper = require('../../common/ClusterTestGeneration.js'); const kGlobalAttributes = [ 0xfff8, // GeneratedCommandList 0xfff9, // AcceptedCommandList + 0xfffa, // EventList 0xfffb, // AttributeList 0xfffc, // ClusterRevision 0xfffd, // FeatureMap @@ -187,6 +188,28 @@ function chip_endpoint_generated_commands_list(options) { return templateUtil.collectBlocks(ret, options, this); } +function chip_endpoint_generated_event_count(options) { + return this.eventList.length +} + +function chip_endpoint_generated_event_list(options) { + let comment = null + + let index = 0 + let ret = '{ \\\n' + this.eventList.forEach((ev) => { + if (ev.comment != comment) { + ret += ` /* ${ev.comment} */ \\\n` + ret += ` /* EventList (index=${index}) */ \\\n` + comment = ev.comment + } + ret += ` ${ev.eventId}, /* ${ev.name} */ \\\n` + index++ + }) + ret += '}\n' + return ret +} + /** * Return endpoint config GENERATED_CLUSTER MACRO * To be used as a replacement of endpoint_cluster_list since this one @@ -258,6 +281,12 @@ function chip_endpoint_cluster_list() { } )`; } + let eventCount = c.eventCount; + let eventList = 'nullptr'; + if (eventCount > 0) { + eventList = `ZAP_GENERATED_EVENTS_INDEX( ${c.eventIndex} )`; + } + ret = ret.concat(` { \\ /* ${c.comment} */ \\ .clusterId = ${c.clusterId}, \\ @@ -268,6 +297,8 @@ function chip_endpoint_cluster_list() { .functions = ${functionArray}, \\ .acceptedCommandList = ${acceptedCommandsListVal} ,\\ .generatedCommandList = ${generatedCommandsListVal} ,\\ + .eventList = ${eventList}, \\ + .eventCount = ${eventCount}, \\ },\\\n`); totalCommands = totalCommands + acceptedCommands + generatedCommands; @@ -920,6 +951,8 @@ exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list; exports.chip_endpoint_data_version_count = chip_endpoint_data_version_count; exports.chip_endpoint_generated_commands_list = chip_endpoint_generated_commands_list; +exports.chip_endpoint_generated_event_count = chip_endpoint_generated_event_count; +exports.chip_endpoint_generated_event_list = chip_endpoint_generated_event_list; exports.asTypedExpression = asTypedExpression; exports.asTypedLiteral = asTypedLiteral; exports.asLowerCamelCase = asLowerCamelCase; diff --git a/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js b/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js index 486b28724f..493d726b58 100644 --- a/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js +++ b/src-electron/generator/matter/app/zap-templates/templates/chip/helper.js @@ -438,7 +438,7 @@ function chip_server_cluster_attributes(options) { } /** - * Creates block iterator over the server side cluster attributes + * Creates block iterator over the server side cluster events * for a given cluster. * * This function is meant to be used inside a {{#chip_server_clusters}} diff --git a/src-electron/util/zcl-util.js b/src-electron/util/zcl-util.js index d6714b7abc..718ff77351 100644 --- a/src-electron/util/zcl-util.js +++ b/src-electron/util/zcl-util.js @@ -75,6 +75,23 @@ function commandComparator(a, b) { return 0 } +/** + * Comparator for sorting events. + * + * @param {*} a + * @param {*} b + * @returns -1, 0 or 1 + */ +function eventComparator(a, b) { + if (a.manufacturerCode < b.manufacturerCode) return -1 + if (a.manufacturerCode > b.manufacturerCode) return 1 + + if (a.hexCode < b.hexCode) return -1 + if (a.hexCode > b.hexCode) return 1 + + return 0 +} + function findStructByName(structs, name) { for (const s of structs) { if (s.name == name) { @@ -783,6 +800,7 @@ async function createCommandSignature(db, packageId, cmd) { exports.clusterComparator = clusterComparator exports.attributeComparator = attributeComparator exports.commandComparator = commandComparator +exports.eventComparator = eventComparator exports.sortStructsByDependency = sortStructsByDependency exports.isEnum = isEnum exports.isBitmap = isBitmap diff --git a/test/gen-template/matter/endpoint-config.zapt b/test/gen-template/matter/endpoint-config.zapt index b025eb2ed1..e896c5c164 100644 --- a/test/gen-template/matter/endpoint-config.zapt +++ b/test/gen-template/matter/endpoint-config.zapt @@ -37,6 +37,13 @@ #define ZAP_GENERATED_COMMANDS_INDEX(index) ((chip::CommandId *) (&generatedCommands[index])) +// clang-format off +#define GENERATED_EVENT_COUNT {{ chip_endpoint_generated_event_count }} +#define GENERATED_EVENTS {{ chip_endpoint_generated_event_list }} +// clang-format on + +#define ZAP_GENERATED_EVENTS_INDEX(index) ((chip::EventId *) (&generatedEvents[index])) + // Cluster function static arrays #define GENERATED_FUNCTION_ARRAYS {{chip_endpoint_generated_functions}} diff --git a/test/test-util.js b/test/test-util.js index 9e38eb4fd7..5df0ce80f6 100644 --- a/test/test-util.js +++ b/test/test-util.js @@ -123,7 +123,7 @@ exports.totalMatterClusters = 58 exports.totalMatterDeviceTypes = 40 exports.totalMatterCommandArgs = 424 exports.totalMatterCommands = 203 -exports.totalMatterAttributes = 509 +exports.totalMatterAttributes = 510 exports.totalMatterTags = 15 exports.totalMatterEvents = 56 exports.totalMatterEventFields = 83 diff --git a/zcl-builtin/matter/global-attributes.xml b/zcl-builtin/matter/global-attributes.xml index 83a1b5e9e1..d848e4b7ec 100644 --- a/zcl-builtin/matter/global-attributes.xml +++ b/zcl-builtin/matter/global-attributes.xml @@ -1,6 +1,6 @@