From 387908060ff252c03183b3249970129e5e382e9f Mon Sep 17 00:00:00 2001 From: Paul Regan <64710345+paulr34@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:46:24 -0500 Subject: [PATCH] Enable Multiple Endpoints and Device Types in Device Composition Insertion (#1489) * enabling ZAP to load multiple devices for an endpoint composition * fixing code so there can be multiple endpoints with different consraints and conformance if necessary * remove debug test * PR review cleanup --- docs/api.md | 9 ++-- src-electron/db/query-loader.js | 72 ++++++++++++++++++++------- src-electron/zcl/zcl-loader-silabs.js | 7 +-- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/docs/api.md b/docs/api.md index e6a1d62c51..8b08d79495 100644 --- a/docs/api.md +++ b/docs/api.md @@ -4066,16 +4066,17 @@ Retrieves the endpoint composition ID for a given device type code. ### DB API: zcl loading queries~insertDeviceComposition(db, deviceType, endpointCompositionId) ⇒ Promise -Inserts a device composition record into the DEVICE_COMPOSITION table. +Inserts device composition records for each deviceType into the DEVICE_COMPOSITION table +for all endpoints in the deviceType, including endpoint-specific constraint and conformance values. This function constructs an SQL INSERT query to add a new record to the -DEVICE_COMPOSITION table. It handles the insertion of the device code, -endpoint composition reference, conformance, and constraint values. +DEVICE_COMPOSITION table for each deviceType in each endpoint. It handles the insertion +of the device code, endpoint composition reference, conformance, and constraint values. Note that the "CONSTRAINT" column name is escaped with double quotes to avoid conflicts with the SQL reserved keyword. **Kind**: inner method of [DB API: zcl loading queries](#module_DB API_ zcl loading queries) -**Returns**: Promise - A promise that resolves when the insertion is complete. +**Returns**: Promise - A promise that resolves when all insertions are complete. | Param | Type | Description | | --- | --- | --- | diff --git a/src-electron/db/query-loader.js b/src-electron/db/query-loader.js index d770c913f8..95f1bbe127 100644 --- a/src-electron/db/query-loader.js +++ b/src-electron/db/query-loader.js @@ -1151,35 +1151,73 @@ async function getEndpointCompositionIdByCode(db, deviceType) { } /** - * Inserts a device composition record into the DEVICE_COMPOSITION table. + * Inserts device composition records for each deviceType into the DEVICE_COMPOSITION table + * for all endpoints in the deviceType, including endpoint-specific constraint and conformance values. * * This function constructs an SQL INSERT query to add a new record to the - * DEVICE_COMPOSITION table. It handles the insertion of the device code, - * endpoint composition reference, conformance, and constraint values. + * DEVICE_COMPOSITION table for each deviceType in each endpoint. It handles the insertion + * of the device code, endpoint composition reference, conformance, and constraint values. * Note that the "CONSTRAINT" column name is escaped with double quotes * to avoid conflicts with the SQL reserved keyword. * * @param {Object} db - The database connection object. * @param {Object} deviceType - The device type object containing the data to be inserted. * @param {number} endpointCompositionId - The ID of the endpoint composition. - * @returns {Promise} A promise that resolves when the insertion is complete. + * @returns {Promise} A promise that resolves when all insertions are complete. */ function insertDeviceComposition(db, deviceType, endpointCompositionId) { - const insertQuery = ` - INSERT INTO DEVICE_COMPOSITION (CODE, ENDPOINT_COMPOSITION_REF, CONFORMANCE, DEVICE_CONSTRAINT) - VALUES (?, ?, ?, ?) - ` - try { - return dbApi.dbInsert(db, insertQuery, [ - parseInt(deviceType.childDeviceId, 16), - endpointCompositionId, - deviceType.conformance, + // Ensure that deviceType and its necessary properties are defined + if (!deviceType?.composition?.endpoint) { + throw new Error('Invalid deviceType object or endpoint data') + } + + // Make sure 'deviceType.composition.endpoint' is always an array, even if there's only one endpoint + const endpoints = Array.isArray(deviceType.composition.endpoint) + ? deviceType.composition.endpoint + : [deviceType.composition.endpoint] + + // Prepare an array to hold all insert queries + const insertQueries = [] + + // Iterate over all endpoints in the deviceType and their respective deviceTypes + for (let endpoint of endpoints) { + // Ensure deviceType is present and handle both single value or array + const deviceTypes = Array.isArray(endpoint.deviceType) + ? endpoint.deviceType + : endpoint.deviceType + ? [endpoint.deviceType] + : [] // Default to empty array if undefined + + // Use the $ to get the endpoint-specific conformance and constraint values + const endpointConformance = + endpoint.endpointComposition?.endpoint?.$.conformance || + deviceType.conformance + const endpointConstraint = + endpoint.endpointComposition?.endpoint?.$.constraint || deviceType.constraint - ]) - } catch (error) { - console.error('Error inserting device composition:', error) - throw error // Re-throw the error after logging it + + // Create insert queries for each deviceType in this endpoint and add them to the insertQueries array + for (let device of deviceTypes) { + insertQueries.push( + dbApi.dbInsert( + db, + ` + INSERT INTO DEVICE_COMPOSITION (CODE, ENDPOINT_COMPOSITION_REF, CONFORMANCE, DEVICE_CONSTRAINT) + VALUES (?, ?, ?, ?) + `, + [ + parseInt(device, 16), // Convert deviceType to integer, assuming it is hex + endpointCompositionId, + endpointConformance, // Use the endpoint's specific conformance if available + endpointConstraint // Use the endpoint's specific constraint if available + ] + ) + ) + } } + + // Return the promise for executing all queries concurrently + return Promise.all(insertQueries) } /** diff --git a/src-electron/zcl/zcl-loader-silabs.js b/src-electron/zcl/zcl-loader-silabs.js index 5a2a89b1da..2fe6022982 100644 --- a/src-electron/zcl/zcl-loader-silabs.js +++ b/src-electron/zcl/zcl-loader-silabs.js @@ -1665,12 +1665,7 @@ function prepareDeviceType(deviceType) { if ('endpointComposition' in deviceType) { try { ret.compositionType = deviceType.endpointComposition[0].compositionType[0] - ret.conformance = - deviceType.endpointComposition[0].endpoint[0].$.conformance - ret.constraint = - deviceType.endpointComposition[0].endpoint[0].$.constraint - ret.childDeviceId = - deviceType.endpointComposition[0].endpoint[0].deviceType[0] + ret.composition = deviceType.endpointComposition[0] } catch (error) { console.error('Error processing endpoint composition:', error) }