diff --git a/apack.json b/apack.json index 173939f22ae373f8127bc4340f3bc7149cf824e4..582c061556e895f031139ed955329c1e06012a19 100644 --- a/apack.json +++ b/apack.json @@ -4,7 +4,7 @@ "description": "Graphical configuration tool for application and libraries based on Zigbee Cluster Library.", "path": [".", "node_modules/.bin/", "ZAP.app/Contents/MacOS"], "requiredFeatureLevel": "apack.core:9", - "featureLevel": 94, + "featureLevel": 95, "uc.triggerExtension": "zap", "executable": { "zap:win32.x86_64": { diff --git a/src-electron/db/db-mapping.js b/src-electron/db/db-mapping.js index 874c6749e967e836320069a8a62533d686bc48dc..363c47ca061809b1e1167232321a24b3e2e719ac 100644 --- a/src-electron/db/db-mapping.js +++ b/src-electron/db/db-mapping.js @@ -179,9 +179,13 @@ exports.map = { argPresentIf: x.ARG_PRESENT_IF, argCountArg: x.ARG_COUNT_ARG, commandArgCount: x.COMMAND_ARGUMENT_COUNT, + requiredCommandArgCount: x.REQUIRED_COMMAND_ARGUMENT_COUNT, + hasArguments: x.COMMAND_ARGUMENT_COUNT > 0, + commandHasRequiredField: x.REQUIRED_COMMAND_ARGUMENT_COUNT > 0, argIsNullable: x.ARG_IS_NULLABLE, responseRef: x.RESPONSE_REF, responseName: x.RESPONSE_NAME, + hasSpecificResponse: dbApi.toDbBool(x.RESPONSE_REF), isIncoming: x.INCOMING, isOutgoing: x.OUTGOING, isDefaultResponseEnabled: x.IS_DEFAULT_RESPONSE_ENABLED, diff --git a/src-electron/db/query-command.js b/src-electron/db/query-command.js index af5fb1c3dccef7ba479e31641b5296966a181985..2b139a38617bd14ca92c231dd30fc40dbd9598f1 100644 --- a/src-electron/db/query-command.js +++ b/src-electron/db/query-command.js @@ -121,7 +121,8 @@ async function selectAllAvailableClusterCommandDetailsFromEndpointTypes( let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString() let mapFunction = (x) => { return { - id: x.CLUSTER_ID, + clusterId: x.CLUSTER_ID, + id: x.COMMAND_ID, clusterName: x.CLUSTER_NAME, clusterCode: x.CLUSTER_CODE, commandMfgCode: x.COMMAND_MANUFACTURER_CODE, @@ -132,6 +133,9 @@ async function selectAllAvailableClusterCommandDetailsFromEndpointTypes( commandName: x.COMMAND_NAME, commandSource: x.COMMAND_SOURCE, commandCode: x.COMMAND_CODE, + code: x.COMMAND_CODE, + name: x.COMMAND_NAME, + source: x.COMMAND_SOURCE, incoming: x.INCOMING, outgoing: x.OUTGOING, mfgCommandCount: x.MANUFACTURING_SPECIFIC_COMMAND_COUNT, @@ -153,6 +157,7 @@ SELECT ENDPOINT_TYPE_CLUSTER.ENABLED AS CLUSTER_ENABLED, COUNT(*) OVER (PARTITION BY CLUSTER.MANUFACTURER_CODE, CLUSTER.NAME, COMMAND.MANUFACTURER_CODE, COMMAND.NAME) AS NO_OF_CLUSTER_SIDES_ENABLED, COMMAND.NAME AS COMMAND_NAME, + COMMAND.COMMAND_ID, COMMAND.SOURCE AS COMMAND_SOURCE, COMMAND.CODE AS COMMAND_CODE, ENDPOINT_TYPE_COMMAND.INCOMING AS INCOMING, @@ -921,7 +926,8 @@ SELECT COMMAND.RESPONSE_REF, COMMAND.RESPONSE_NAME, COMMAND.IS_DEFAULT_RESPONSE_ENABLED, - COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT + COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT, + COUNT(COMMAND_ARG.COMMAND_REF) FILTER (WHERE COMMAND_ARG.IS_OPTIONAL = 0) AS REQUIRED_COMMAND_ARGUMENT_COUNT FROM COMMAND LEFT JOIN COMMAND_ARG diff --git a/src-electron/db/query-endpoint-type.js b/src-electron/db/query-endpoint-type.js index f8a7ea2feac69c5bbf77cf0629c291d4beb2d2e2..bd8b0cbbd280d72ca30128d048a8339fe09709b0 100644 --- a/src-electron/db/query-endpoint-type.js +++ b/src-electron/db/query-endpoint-type.js @@ -162,7 +162,17 @@ async function selectEndpointType(db, id) { * @param {*} endpointTypes * @returns Promise that resolves with the data that should go into the external form. */ -async function selectAllClustersDetailsFromEndpointTypes(db, endpointTypes) { +async function selectAllClustersDetailsFromEndpointTypes( + db, + endpointTypes, + options = null +) { + let side = null + let endpointClusterSideFilter = 'ENDPOINT_TYPE_CLUSTER.SIDE IS NOT ""' + if (options && options.hash.side) { + side = options.hash.side.toLowerCase() + endpointClusterSideFilter = "ENDPOINT_TYPE_CLUSTER.SIDE = '" + side + "'" + } let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString() let mapFunction = (x) => { return { @@ -205,7 +215,7 @@ ON WHERE ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds}) AND - ENDPOINT_TYPE_CLUSTER.SIDE IS NOT "" AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1 +${endpointClusterSideFilter} AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1 GROUP BY NAME, SIDE ${ diff --git a/src-electron/generator/helper-session.js b/src-electron/generator/helper-session.js index 67efb6b1f114c868fa74ef532c6078153a45db74..f57f3cc6c320be8e183eb002f9342c0fb0850b61 100644 --- a/src-electron/generator/helper-session.js +++ b/src-electron/generator/helper-session.js @@ -451,7 +451,8 @@ async function all_user_clusters(options) { let clusters = await queryEndpointType.selectAllClustersDetailsFromEndpointTypes( this.global.db, - endpointTypes + endpointTypes, + options ) return templateUtil.collectBlocks(clusters, options, this) diff --git a/src-electron/generator/helper-zcl.js b/src-electron/generator/helper-zcl.js index 364cf14234a07fcdf3020925251d73a5556370ad..396e0807af98a0ee3a9018764b699492426e9248 100644 --- a/src-electron/generator/helper-zcl.js +++ b/src-electron/generator/helper-zcl.js @@ -405,6 +405,38 @@ function zcl_commands(options) { return templateUtil.templatePromise(this.global, promise) } +/** + * Returns all commands which are command responses. + * For eg, If the xml has the following: + * <command source="client" code="0x00" name="newCmd" response="newCmdResponse"> + * then newCmdResponse will be included in the list of commands returned here. + * + * There are two modes of this helper: + * - when used in a global context, it iterates over ALL command responses in + * the database. + * - when used inside a `zcl_cluster` block helper, it iterates only over the + * commands responses for that cluster. + * @param {*} options + * @returns all command responses + */ +async function zcl_command_responses(options) { + let packageIds = await templateUtil.ensureZclPackageIds(this) + let cmds = null + if ('id' in this) { + cmds = await queryCommand.selectCommandsByClusterId( + this.global.db, + this.id, + packageIds + ) + } else { + cmds = await queryCommand.selectAllCommands(this.global.db, packageIds) + } + let commandResponses = cmds.map((cmd) => cmd.responseName) + let res = cmds.filter((cmd) => commandResponses.includes(cmd.name)) + let promise = templateUtil.collectBlocks(res, options, this) + return templateUtil.templatePromise(this.global, promise) +} + /** * Block helper iterating over all commands with cluster information. * Note: Similar to zcl_commands but has cluster information as well. @@ -2954,3 +2986,4 @@ exports.as_zcl_type_size = as_zcl_type_size exports.if_compare = if_compare exports.if_is_data_type_signed = if_is_data_type_signed exports.as_zcl_data_type_size = as_zcl_data_type_size +exports.zcl_command_responses = zcl_command_responses 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 19f3db722c4aab6dfba17932dd4681208df8312e..fdd419b6365e4b35bb6ccb737984a49fdd50b6bb 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 @@ -752,16 +752,27 @@ const dep = templateUtil.deprecatedHelper; // exports.chip_clusters = chip_clusters; exports.chip_has_clusters = chip_has_clusters; -exports.chip_client_clusters = chip_client_clusters; +exports.chip_client_clusters = dep( + chip_client_clusters, + 'chip_client_clusters has been deprecated. Use all_user_clusters with the \ + side option as client' +); exports.chip_has_client_clusters = chip_has_client_clusters; exports.chip_server_clusters = chip_server_clusters; exports.chip_has_server_clusters = chip_has_server_clusters; -exports.chip_cluster_commands = chip_cluster_commands; -exports.chip_cluster_command_arguments = chip_cluster_command_arguments; +exports.chip_cluster_commands = dep( + chip_cluster_commands, + 'chip_cluster_commands has been deprecated. Use zcl_commands with source attribute as client' +); +exports.chip_cluster_command_arguments = dep(chip_cluster_command_arguments, { + to: 'zcl_command_arguments', +}); exports.chip_cluster_command_arguments_with_structs_expanded = chip_cluster_command_arguments_with_structs_expanded; exports.chip_server_global_responses = chip_server_global_responses; -exports.chip_cluster_responses = chip_cluster_responses; +exports.chip_cluster_responses = dep(chip_cluster_responses, { + to: 'zcl_command_responses', +}); exports.chip_cluster_response_arguments = chip_cluster_response_arguments; exports.chip_attribute_list_entryTypes = chip_attribute_list_entryTypes; exports.chip_server_cluster_attributes = dep( diff --git a/src-electron/generator/matter/controller/java/templates/helper.js b/src-electron/generator/matter/controller/java/templates/helper.js index 66c2fed7414978065cd2996288f3b315a7f3b895..50ccf9a600f708043c9f7c56186ccfa2b0392a90 100644 --- a/src-electron/generator/matter/controller/java/templates/helper.js +++ b/src-electron/generator/matter/controller/java/templates/helper.js @@ -193,8 +193,7 @@ function convertAttributeCallbackTypeToJavaName(cType) { } /** - * Note: This helper needs to be used under a block helper which has a - * reference to clusterId. + * Note: This is a util function * Available options: * - isBoxedJavaType: 0/1 to return string types in different ways * - All other options passed to this helper are considered as overrides for @@ -206,7 +205,12 @@ function convertAttributeCallbackTypeToJavaName(cType) { * @param {*} options * @returns The corresponding java data type for a zcl data type. */ -async function as_underlying_java_zcl_type(type, clusterId, options) { +async function as_underlying_java_zcl_type_util( + type, + clusterId, + options, + context +) { let hash = options.hash; // Overwrite any type with the one coming from the template options // Eg: {{as_underlying_java_zcl_type type [clusterId] boolean='Boolean'}} @@ -216,9 +220,9 @@ async function as_underlying_java_zcl_type(type, clusterId, options) { } // Get ZCL Data Type from the db - const packageIds = await templateUtil.ensureZclPackageIds(this); + const packageIds = await templateUtil.ensureZclPackageIds(context); let dataType = await queryZcl.selectDataTypeByNameAndClusterId( - this.global.db, + context.global.db, type, clusterId, packageIds @@ -247,7 +251,7 @@ async function as_underlying_java_zcl_type(type, clusterId, options) { dataType, clusterId, packageIds, - this + context ); if (sizeAndSign.size >= 3) { return 'Long'; @@ -268,6 +272,24 @@ async function as_underlying_java_zcl_type(type, clusterId, options) { } } +/** + * Note: This helper needs to be used under a block helper which has a + * reference to clusterId. + * Available options: + * - isBoxedJavaType: 0/1 to return string types in different ways + * - All other options passed to this helper are considered as overrides for + * zcl types + * for eg: (as_underlying_java_zcl_type type clusterId boolean='Boolean') + * will return "Boolean" for "boolean" type + * @param {*} type + * @param {*} clusterId + * @param {*} options + * @returns The corresponding java data type for a zcl data type. + */ +async function as_underlying_java_zcl_type(type, clusterId, options) { + return as_underlying_java_zcl_type_util(type, clusterId, options, this); +} + async function asUnderlyingBasicType(type) { const options = { hash: {} }; let zclType = await zclHelper.asUnderlyingZclType.call(this, type, options); @@ -295,7 +317,16 @@ async function asJavaType(type, zclType, cluster, options) { cluster )}Cluster${appHelper.asUpperCamelCase(type)}`; } else { - classType += asJavaBoxedType(type, zclType); + let javaBoxedType = asJavaBoxedType(type, zclType); + if (javaBoxedType == 'Object' && options.hash.clusterId) { + javaBoxedType = await as_underlying_java_zcl_type_util( + type, + options.hash.clusterId, + options, + this + ); + } + classType += javaBoxedType; } if (!options.hash.underlyingType) { diff --git a/src-electron/generator/matter/controller/python/templates/helper.js b/src-electron/generator/matter/controller/python/templates/helper.js index 1b06f53d8c01e006107b29c996e4fea121de92d4..de12a955c8f0f6f9c46ea76cc0cc9448df975880 100644 --- a/src-electron/generator/matter/controller/python/templates/helper.js +++ b/src-electron/generator/matter/controller/python/templates/helper.js @@ -79,7 +79,7 @@ async function as_underlying_python_zcl_type(type, clusterId, options) { clusterId, packageIds ); - if (type == 'boolean') { + if (type && type.toLowerCase() == 'boolean') { return 'bool'; } else if ( dataType.discriminatorName.toLowerCase() == dbEnum.zclType.bitmap ||