blob: ac289daf59ed5455e7ffd51d9ad0fba90ccd012a [file] [log] [blame]
/**
*
* Copyright (c) 2021 Silicon Labs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This module provides queries related to commands.
*
* @module DB API: command queries.
*/
const dbApi = require('./db-api.js')
const dbMapping = require('./db-mapping.js')
/**
* Promises to select all endpoint type commands filtered by EndpointTypeRef and ClusterRef.
*
* @export
* @param {*} db
* @param {*} endpointTypeRef
* @param {*} endpointTypeClusterRef
* @returns Records of selected Endpoint Type Commands.
*/
async function selectEndpointTypeCommandsByEndpointTypeRefAndClusterRef(
db,
endpointTypeRef,
endpointTypeClusterRef
) {
let rows = await dbApi.dbAll(
db,
`
SELECT
ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_COMMAND_ID,
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF,
ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF AS 'CLUSTER_REF',
ENDPOINT_TYPE_COMMAND.COMMAND_REF,
ENDPOINT_TYPE_COMMAND.IS_INCOMING,
ENDPOINT_TYPE_COMMAND.IS_ENABLED
FROM
ENDPOINT_TYPE_COMMAND
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF = ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF = ?
AND
ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF = ?`,
[endpointTypeRef, endpointTypeClusterRef]
)
return rows.map(dbMapping.map.endpointTypeCommand)
}
/**
* Promises to duplicate endpoint type commands.
*
* @export
* @param {*} db
* @param {*} newEndpointTypeClusterRef
* @param {*} command
* @returns Promise duplicated endpoint type command's id.
*/
async function duplicateEndpointTypeCommand(
db,
newEndpointTypeClusterRef,
command
) {
return await dbApi.dbInsert(
db,
`INSERT INTO
ENDPOINT_TYPE_COMMAND (
ENDPOINT_TYPE_CLUSTER_REF,
COMMAND_REF,
IS_INCOMING,
IS_ENABLED
)
VALUES (
?,
?,
?,
?
)`,
[
newEndpointTypeClusterRef,
command.commandRef,
command.isIncoming,
command.isEnabled
]
)
}
/**
* Returns the count of the number of cluster commands with cli for a cluster
* @param {*} db
* @param {*} endpointTypes
* @param {*} endpointClusterId
* @param {*} packageIds
*/
async function selectCliCommandCountFromEndpointTypeCluster(
db,
endpointTypes,
endpointClusterId,
packageIds
) {
let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
let res = await dbApi.dbAll(
db,
`
SELECT
COUNT(*) AS COUNT
FROM
COMMAND
INNER JOIN CLUSTER
ON COMMAND.CLUSTER_REF = CLUSTER.CLUSTER_ID
INNER JOIN ENDPOINT_TYPE_CLUSTER
ON ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
INNER JOIN PACKAGE_OPTION
ON PACKAGE_OPTION.OPTION_CODE = COMMAND.NAME
WHERE ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ?
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
`,
[endpointClusterId]
)
return res[0].COUNT
}
/**
*
* @param db
* @param endpointClusterId
* @param packageIds
* Returns: A promise with all commands with cli for a given cluster id
*/
async function selectCliCommandsFromCluster(db, endpointClusterId, packageIds) {
let mapFunction = (x) => {
return {
name: x.NAME,
code: x.CODE,
mfgCode: x.MANUFACTURER_CODE,
source: x.SOURCE
}
}
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.NAME,
COMMAND.CODE,
COMMAND.MANUFACTURER_CODE,
COMMAND.SOURCE
FROM
COMMAND
INNER JOIN
CLUSTER
ON
COMMAND.CLUSTER_REF = CLUSTER.CLUSTER_ID
INNER JOIN
PACKAGE_OPTION
ON
PACKAGE_OPTION.OPTION_CODE = COMMAND.NAME
WHERE CLUSTER.CLUSTER_ID = ? AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(
packageIds
)})`,
[endpointClusterId]
)
.then((rows) => rows.map(mapFunction))
}
/**
* All available cluster command detals across all endpoints and clusters.
* @param db
* @param endpointTypes
* @param packageIds
* @returns Available Cluster command details across given endpoints and clusters.
* Note: The relationship between the endpoint_type_cluster being enabled and a
* endpoint_type_command is indirect. The reason for this being the endpoint
* type command is not precisely linked to the sides of the cluster as commands
* do not belong to a side of a cluster like an attribute.
*/
async function selectAllAvailableClusterCommandDetailsFromEndpointTypes(
db,
endpointTypes,
packageIds
) {
let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
let mapFunction = (x) => {
return {
clusterId: x.CLUSTER_ID,
id: x.COMMAND_ID,
clusterName: x.CLUSTER_NAME,
clusterCode: x.CLUSTER_CODE,
commandMfgCode: x.COMMAND_MANUFACTURER_CODE,
clusterMfgCode: x.CLUSTER_MANUFACTURER_CODE,
clusterSide: x.CLUSTER_SIDE,
clusterEnabled: x.CLUSTER_ENABLED,
numberOfClusterSidesEnabled: x.NO_OF_CLUSTER_SIDES_ENABLED,
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,
hasSpecificResponse: dbApi.toDbBool(x.RESPONSE_REF),
responseName: x.RESPONSE_NAME,
commandArgCount: x.COMMAND_ARGUMENT_COUNT,
requiredCommandArgCount: x.REQUIRED_COMMAND_ARGUMENT_COUNT,
hasArguments: x.COMMAND_ARGUMENT_COUNT > 0,
mustUseTimedInvoke: dbApi.fromDbBool(x.MUST_USE_TIMED_INVOKE)
}
}
return dbApi
.dbAll(
db,
`
SELECT * FROM (
SELECT
CLUSTER.CLUSTER_ID,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CODE AS CLUSTER_CODE,
COMMAND.MANUFACTURER_CODE AS COMMAND_MANUFACTURER_CODE,
CLUSTER.MANUFACTURER_CODE AS CLUSTER_MANUFACTURER_CODE,
ENDPOINT_TYPE_CLUSTER.SIDE AS CLUSTER_SIDE,
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,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS INCOMING,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS OUTGOING,
COUNT(COMMAND.MANUFACTURER_CODE) OVER () AS MANUFACTURING_SPECIFIC_COMMAND_COUNT,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.MUST_USE_TIMED_INVOKE,
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
INNER JOIN
ENDPOINT_TYPE_COMMAND
ON
ENDPOINT_TYPE_COMMAND.COMMAND_REF = COMMAND.COMMAND_ID
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF
INNER JOIN
CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
LEFT JOIN
COMMAND_ARG
ON
COMMAND.COMMAND_ID = COMMAND_ARG.COMMAND_REF
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_CLUSTER.SIDE IN ("client", "server") AND ENDPOINT_TYPE_CLUSTER.ENABLED=1
AND (
(ENDPOINT_TYPE_COMMAND.IS_INCOMING=1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED=1) OR
(ENDPOINT_TYPE_COMMAND.IS_INCOMING=0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED=1)
)
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
CLUSTER.MANUFACTURER_CODE,
CLUSTER.NAME,
COMMAND.MANUFACTURER_CODE,
COMMAND.NAME,
ENDPOINT_TYPE_CLUSTER.SIDE )
GROUP BY
CLUSTER_MANUFACTURER_CODE,
CLUSTER_NAME,
COMMAND_MANUFACTURER_CODE,
COMMAND_NAME
ORDER BY
CLUSTER_MANUFACTURER_CODE, CLUSTER_CODE, COMMAND_MANUFACTURER_CODE, COMMAND_CODE`
)
.then((rows) => rows.map(mapFunction))
}
/**
* All Clusters with available incoming or outgoing commands.
* @param db
* @param endpointTypes
* @param uniqueClusterCodes
* @param isIncoming
* @param packageIds
* @returns All Clusters with side that have available incoming or outgoing
* commands.
* uniqueClusterCodes can be used to get unique clusters based on a cluster code
* and this can eliminate duplicate cluster code entries when manufacturing
* specific clusters exist with the same cluster code.
* Note: The relationship between the endpoint_type_cluster being enabled and a
* endpoint_type_command is indirect. The reason for this being the endpoint
* type command is not precisely linked to the sides of the cluster as commands
* do not belong to a side of a cluster like an attribute.
*/
async function selectAllClustersWithIncomingOrOutgoingCommands(
db,
endpointTypes,
uniqueClusterCodes,
isIncoming,
packageIds
) {
let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
let sqlGroupBy = uniqueClusterCodes ? 'CLUSTER.CODE' : 'CLUSTER.NAME'
let isIncomingOrOutgoingSql = isIncoming
? `ENDPOINT_TYPE_COMMAND.IS_INCOMING = 1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED=1`
: `ENDPOINT_TYPE_COMMAND.IS_INCOMING = 0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED=1`
let mapFunction = (x) => {
return {
id: x.CLUSTER_ID,
clusterName: x.CLUSTER_NAME,
code: x.CLUSTER_CODE,
clusterDefine: x.CLUSTER_DEFINE,
clusterMfgCode: x.MANUFACTURER_CODE,
clusterSide: x.CLUSTER_SIDE,
clusterEnabled: x.CLUSTER_ENABLED,
endpointClusterId: x.ENDPOINT_TYPE_CLUSTER_ID
}
}
return dbApi
.dbAll(
db,
`
SELECT
CLUSTER.CLUSTER_ID,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CODE AS CLUSTER_CODE,
CLUSTER.DEFINE AS CLUSTER_DEFINE,
CLUSTER.MANUFACTURER_CODE AS MANUFACTURER_CODE,
ENDPOINT_TYPE_CLUSTER.SIDE AS CLUSTER_SIDE,
ENDPOINT_TYPE_CLUSTER.ENABLED AS CLUSTER_ENABLED,
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
FROM
COMMAND
INNER JOIN
ENDPOINT_TYPE_COMMAND
ON
ENDPOINT_TYPE_COMMAND.COMMAND_REF = COMMAND.COMMAND_ID
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF
INNER JOIN
CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_CLUSTER.SIDE IN ("client", "server")
AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1 AND ${isIncomingOrOutgoingSql}
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
${sqlGroupBy}, ENDPOINT_TYPE_CLUSTER.SIDE ORDER BY CLUSTER.NAME, ENDPOINT_TYPE_CLUSTER.SIDE`
)
.then((rows) => rows.map(mapFunction))
}
/**
* All Clusters with available incoming commands.
* @param db
* @param endpointTypes
* @param uniqueClusterCodes
* @param packageIds
* @returns All Clusters with side that have available incoming commands.
* uniqueClusterCodes can be used to get unique clusters based on a cluster code
* and this can eliminate duplicate cluster code entries when manufacturing
* specific clusters exist with the same cluster code.
* Note: The relationship between the endpoint_type_cluster being enabled and a
* endpoint_type_command is indirect. The reason for this being the endpoint
* type command is not precisely linked to the sides of the cluster as commands
* do not belong to a side of a cluster like an attribute.
*/
async function selectAllClustersWithIncomingCommands(
db,
endpointTypes,
uniqueClusterCodes = false,
packageIds
) {
return selectAllClustersWithIncomingOrOutgoingCommands(
db,
endpointTypes,
uniqueClusterCodes,
true,
packageIds
)
}
/**
* All Clusters with available outgoing commands.
* @param db
* @param endpointTypes
* @param uniqueClusterCodes
* @param packageIds
* @returns All Clusters with side that have available outgoing commands.
* uniqueClusterCodes can be used to get unique clusters based on a cluster code
* and this can eliminate duplicate cluster code entries when manufacturing
* specific clusters exist with the same cluster code.
* Note: The relationship between the endpoint_type_cluster being enabled and a
* endpoint_type_command is indirect. The reason for this being the endpoint
* type command is not precisely linked to the sides of the cluster as commands
* do not belong to a side of a cluster like an attribute.
*/
async function selectAllClustersWithOutgoingCommands(
db,
endpointTypes,
uniqueClusterCodes = false,
packageIds
) {
return selectAllClustersWithIncomingOrOutgoingCommands(
db,
endpointTypes,
uniqueClusterCodes,
false,
packageIds
)
}
/**
* All Manufacturing Clusters with available incoming commands for a given
* cluster code.
* @param db
* @param endpointTypes
* @param clusterCode
* @param packageIds
* @returns All Manufacturing Clusters with available incoming commands for a
* given cluster code.
* Note: The relationship between the endpoint_type_cluster being enabled and a
* endpoint_type_command is indirect. The reason for this being the endpoint
* type command is not precisely linked to the sides of the cluster as commands
* do not belong to a side of a cluster like an attribute.
*/
async function selectMfgClustersWithIncomingCommandsForClusterCode(
db,
endpointTypes,
clusterCode,
packageIds
) {
let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
let mapFunction = (x) => {
return {
id: x.CLUSTER_ID,
clusterName: x.CLUSTER_NAME,
code: x.CLUSTER_CODE,
clusterDefine: x.CLUSTER_DEFINE,
clusterMfgCode: x.MANUFACTURER_CODE,
clusterSide: x.CLUSTER_SIDE,
clusterEnabled: x.CLUSTER_ENABLED,
endpointClusterId: x.ENDPOINT_TYPE_CLUSTER_ID
}
}
return dbApi
.dbAll(
db,
`
SELECT
CLUSTER.CLUSTER_ID,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CODE AS CLUSTER_CODE,
CLUSTER.DEFINE AS CLUSTER_DEFINE,
CLUSTER.MANUFACTURER_CODE AS MANUFACTURER_CODE,
ENDPOINT_TYPE_CLUSTER.SIDE AS CLUSTER_SIDE,
ENDPOINT_TYPE_CLUSTER.ENABLED AS CLUSTER_ENABLED,
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
FROM
COMMAND
INNER JOIN
ENDPOINT_TYPE_COMMAND
ON
ENDPOINT_TYPE_COMMAND.COMMAND_REF = COMMAND.COMMAND_ID
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF
INNER JOIN
CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_CLUSTER.SIDE IN ("client", "server")
AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1
AND ENDPOINT_TYPE_COMMAND.IS_INCOMING = 1
AND ENDPOINT_TYPE_COMMAND.IS_ENABLED = 1
AND COMMAND.SOURCE != ENDPOINT_TYPE_CLUSTER.SIDE
AND CLUSTER.CODE = ${clusterCode}
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
CLUSTER.NAME, ENDPOINT_TYPE_CLUSTER.SIDE
ORDER BY
CLUSTER.NAME, ENDPOINT_TYPE_CLUSTER.SIDE`
)
.then((rows) => rows.map(mapFunction))
}
/**
* All Clusters with available incoming commands. This function seeks to consolidate endpoint type clusters
* that are differentiated by sides into one entry.
* @param db
* @param endpointTypes
* @param packageIds
* @returns All Clusters that have available incoming commands.
* Note: The relationship between the endpoint_type_cluster being enabled and a
* endpoint_type_command is indirect. The reason for this being the endpoint
* type command is not precisely linked to the sides of the cluster as commands
* do not belong to a side of a cluster like an attribute.
*/
async function selectAllClustersWithIncomingCommandsCombined(
db,
endpointTypes,
packageIds
) {
let uncombinedClusters = selectAllClustersWithIncomingCommands(
db,
endpointTypes,
packageIds
)
let reduceFunction = (combinedClusters, currentValue) => {
// Find out if current cluster is in combinedClusters, or just use currentValue otherwise.
let newVal = combinedClusters.has(currentValue.id)
? combinedClusters.get(currentValue.id)
: currentValue
//Add side enabled keys
if (currentValue.clusterSide == 'client') {
newVal['clientSideEnabled'] = true
} else if (currentValue.clusterSide == 'server') {
newVal['serverSideEnabled'] = true
}
// Delete extraneous keys
delete newVal['clusterSide']
delete newVal['enabled']
combinedClusters.set(currentValue.id, newVal)
return combinedClusters
}
return uncombinedClusters.then((rows) => {
return Array.from(
rows.reduce(reduceFunction, new Map()),
(value, key) => value[1]
)
})
}
/**
* This function returns all incoming commands that are on enabled sides for a cluster.
* @param db
* @param endpointTypes
* @param clName
* @param clientSideEnabled
* @param serverSideEnabled
* @param isMfgSpecific
* @param packageIds
* @return All commands that are enabled on their incoming side. This is unique based on the command name across a cluster.
*
*/
async function selectAllIncomingCommandsForClusterCombined(
db,
endpointTypes,
clName,
clientSideEnabled,
serverSideEnabled,
isMfgSpecific,
packageIds
) {
let client = clientSideEnabled
? await selectAllIncomingCommandsForCluster(
db,
endpointTypes,
clName,
'client',
isMfgSpecific,
packageIds
)
: []
let server = serverSideEnabled
? await selectAllIncomingCommandsForCluster(
db,
endpointTypes,
clName,
'server',
isMfgSpecific,
packageIds
)
: []
// The assumption here is that, given that this is inside a cluster already; that the command name are unique and sufficient outside of
// the clusterSide duplication.
let combinedClusters = client.concat(server)
let reduceFunction = (combinedMap, currentValue) => {
if (!combinedMap.has(currentValue.commandName)) {
combinedMap.set(currentValue.commandName, currentValue)
}
return combinedMap
}
return Array.from(
combinedClusters.reduce(reduceFunction, new Map()),
(value, key) => value[1]
)
}
/**
*
* @param db
* @param endpointTypes
* @param clName
* @param clSide
* @param isMfgSpecific
* @param isIncoming
* @param packageIds
* @returns Incoming or Outgoing commands for a given cluster
*/
async function selectAllIncomingOrOutgoingCommandsForCluster(
db,
endpointTypes,
clName,
clSide,
isMfgSpecific,
isIncoming,
packageIds
) {
let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
let mfgSpecificString =
isMfgSpecific === undefined
? ``
: isMfgSpecific
? ` AND COMMAND.MANUFACTURER_CODE IS NOT NULL `
: ` AND COMMAND.MANUFACTURER_CODE IS NULL `
let isIncomingOrOutgoingSql = isIncoming
? `ENDPOINT_TYPE_COMMAND.IS_INCOMING = 1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED=1`
: `ENDPOINT_TYPE_COMMAND.IS_INCOMING = 0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED=1`
let mapFunction = (x) => {
return {
clusterId: x.CLUSTER_ID,
clusterName: x.CLUSTER_NAME,
clusterCode: x.CLUSTER_CODE,
clusterDefine: x.CLUSTER_DEFINE,
commandMfgCode: x.COMMAND_MANUFACTURER_CODE,
clusterSide: x.CLUSTER_SIDE,
clusterEnabled: x.CLUSTER_ENABLED,
endpointClusterId: x.ENDPOINT_TYPE_CLUSTER_ID,
numberOfClusterSidesEnabled: x.NO_OF_CLUSTER_SIDES_ENABLED,
id: x.COMMAND_ID,
commandName: x.COMMAND_NAME,
commandSource: x.COMMAND_SOURCE,
code: x.COMMAND_CODE,
mustUseTimedInvoke: dbApi.fromDbBool(x.MUST_USE_TIMED_INVOKE),
isFabricScoped: dbApi.fromDbBool(x.IS_FABRIC_SCOPED),
responseName: x.RESPONSE_NAME,
responseRef: x.RESPONSE_REF,
incoming: x.INCOMING,
outgoing: x.OUTGOING,
mfgCommandCount: x.MANUFACTURING_SPECIFIC_COMMAND_COUNT
}
}
return dbApi
.dbAll(
db,
`
SELECT
CLUSTER.CLUSTER_ID,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CODE AS CLUSTER_CODE,
CLUSTER.DEFINE AS CLUSTER_DEFINE,
COMMAND.MANUFACTURER_CODE AS COMMAND_MANUFACTURER_CODE,
ENDPOINT_TYPE_CLUSTER.SIDE AS CLUSTER_SIDE,
ENDPOINT_TYPE_CLUSTER.ENABLED AS CLUSTER_ENABLED,
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID,
COUNT(*) OVER (PARTITION BY CLUSTER.NAME, COMMAND.NAME) AS NO_OF_CLUSTER_SIDES_ENABLED,
COMMAND.COMMAND_ID AS COMMAND_ID,
COMMAND.NAME AS COMMAND_NAME,
COMMAND.SOURCE AS COMMAND_SOURCE,
COMMAND.CODE AS COMMAND_CODE,
COMMAND.MUST_USE_TIMED_INVOKE AS MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED AS IS_FABRIC_SCOPED,
COMMAND.RESPONSE_NAME AS RESPONSE_NAME,
COMMAND.RESPONSE_REF AS RESPONSE_REF,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS INCOMING,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS OUTGOING,
COUNT(COMMAND.MANUFACTURER_CODE) OVER () AS MANUFACTURING_SPECIFIC_COMMAND_COUNT
FROM COMMAND
INNER JOIN ENDPOINT_TYPE_COMMAND
ON ENDPOINT_TYPE_COMMAND.COMMAND_REF = COMMAND.COMMAND_ID
INNER JOIN ENDPOINT_TYPE_CLUSTER
ON ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF
INNER JOIN CLUSTER
ON ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_CLUSTER.SIDE IN ("client", "server") AND ENDPOINT_TYPE_CLUSTER.ENABLED=1 AND ${isIncomingOrOutgoingSql}
AND CLUSTER.NAME = "${clName}" AND ENDPOINT_TYPE_CLUSTER.SIDE = "${clSide}"
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
${mfgSpecificString} GROUP BY COMMAND.NAME
ORDER BY CLUSTER.MANUFACTURER_CODE, CLUSTER.CODE, COMMAND.MANUFACTURER_CODE, COMMAND.CODE`
)
.then((rows) => rows.map(mapFunction))
}
/**
*
* @param db
* @param endpointTypes
* @param clName
* @param clSide
* @param isMfgSpecific,
* @param packageIds
* @returns Incoming Commands for a given cluster
*/
async function selectAllIncomingCommandsForCluster(
db,
endpointTypes,
clName,
clSide,
isMfgSpecific,
packageIds
) {
return selectAllIncomingOrOutgoingCommandsForCluster(
db,
endpointTypes,
clName,
clSide,
isMfgSpecific,
true,
packageIds
)
}
/**
*
* @param db
* @param endpointTypes
* @param clName
* @param clSide
* @param isMfgSpecific
* @param packageIds
* @returns Outgoing Commands for a given cluster
*/
async function selectAllOutgoingCommandsForCluster(
db,
endpointTypes,
clName,
clSide,
isMfgSpecific,
packageIds
) {
return selectAllIncomingOrOutgoingCommandsForCluster(
db,
endpointTypes,
clName,
clSide,
isMfgSpecific,
false,
packageIds
)
}
/**
* Returns all incoming commands.
* @param {*} db
* @param {*} endpointTypes
* @param {*} isMfgSpecific
* @param {*} packageIds
* @returns promise of all incoming commands.
*/
async function selectAllIncomingCommands(
db,
endpointTypes,
isMfgSpecific,
packageIds
) {
let endpointTypeIds = endpointTypes.map((ep) => ep.endpointTypeId).toString()
let mfgSpecificString =
isMfgSpecific === undefined
? ``
: isMfgSpecific
? ` AND COMMAND.MANUFACTURER_CODE IS NOT NULL `
: ` AND COMMAND.MANUFACTURER_CODE IS NULL `
let mapFunction = (x) => {
return {
clusterId: x.CLUSTER_ID,
clusterName: x.CLUSTER_NAME,
clusterCode: x.CLUSTER_CODE,
clusterDefine: x.CLUSTER_DEFINE,
commandMfgCode: x.COMMAND_MANUFACTURER_CODE,
clusterSide: x.CLUSTER_SIDE,
clusterEnabled: x.CLUSTER_ENABLED,
endpointClusterId: x.ENDPOINT_TYPE_CLUSTER_ID,
numberOfClusterSidesEnabled: x.NO_OF_CLUSTER_SIDES_ENABLED,
id: x.COMMAND_ID,
commandName: x.COMMAND_NAME,
commandSource: x.COMMAND_SOURCE,
code: x.COMMAND_CODE,
mustUseTimedInvoke: dbApi.fromDbBool(x.MUST_USE_TIMED_INVOKE),
isFabricScoped: dbApi.fromDbBool(x.IS_FABRIC_SCOPED),
incoming: x.INCOMING,
outgoing: x.OUTGOING,
mfgCommandCount: x.MANUFACTURING_SPECIFIC_COMMAND_COUNT
}
}
return dbApi
.dbAll(
db,
`
SELECT
CLUSTER.CLUSTER_ID,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CODE AS CLUSTER_CODE,
CLUSTER.DEFINE AS CLUSTER_DEFINE,
COMMAND.MANUFACTURER_CODE AS COMMAND_MANUFACTURER_CODE,
ENDPOINT_TYPE_CLUSTER.SIDE AS CLUSTER_SIDE,
ENDPOINT_TYPE_CLUSTER.ENABLED AS CLUSTER_ENABLED,
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID,
COUNT(*) OVER (PARTITION BY CLUSTER.NAME, COMMAND.NAME) AS NO_OF_CLUSTER_SIDES_ENABLED,
COMMAND.COMMAND_ID AS COMMAND_ID,
COMMAND.NAME AS COMMAND_NAME,
COMMAND.SOURCE AS COMMAND_SOURCE,
COMMAND.CODE AS COMMAND_CODE,
COMMAND.MUST_USE_TIMED_INVOKE AS MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED AS IS_FABRIC_SCOPED,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS INCOMING,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS OUTGOING,
COUNT(COMMAND.MANUFACTURER_CODE) OVER () AS MANUFACTURING_SPECIFIC_COMMAND_COUNT
FROM
COMMAND
INNER JOIN
ENDPOINT_TYPE_COMMAND
ON
ENDPOINT_TYPE_COMMAND.COMMAND_REF = COMMAND.COMMAND_ID
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF
INNER JOIN
CLUSTER
ON
ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_CLUSTER.SIDE IN ("client", "server") AND ENDPOINT_TYPE_CLUSTER.ENABLED=1
AND ENDPOINT_TYPE_COMMAND.IS_INCOMING=1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED = 1
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
${mfgSpecificString} GROUP BY CLUSTER.NAME, COMMAND.NAME
ORDER BY CLUSTER.NAME, COMMAND.NAME`
)
.then((rows) => rows.map(mapFunction))
}
/**
* Get command by command code and given package ID.
* @param {*} db
* @param {*} packageId
* @param {*} clusterCode
* @param {*} commandCode
* @param {*} mfgCode
* @returns Promise of command.
*/
async function selectCommandByCode(
db,
packageId,
clusterCode,
commandCode,
mfgCode = null
) {
if (clusterCode == null) {
return selectGlobalCommandByCode(db, packageId, commandCode, mfgCode)
} else {
return selectNonGlobalCommandByCode(
db,
packageId,
clusterCode,
commandCode,
mfgCode
)
}
}
/**
* Get command that is not a global command by command code and package ID.
* @param {*} db
* @param {*} packageId
* @param {*} clusterCode
* @param {*} commandCode
* @param {*} mfgCode
* @returns Promise of command.
*/
async function selectNonGlobalCommandByCode(
db,
packageId,
clusterCode,
commandCode,
mfgCode = null
) {
let query = `
SELECT
C.COMMAND_ID,
C.CLUSTER_REF,
C.PACKAGE_REF,
C.CODE,
C.MANUFACTURER_CODE,
C.NAME,
C.DESCRIPTION,
C.SOURCE,
C.IS_OPTIONAL,
C.MUST_USE_TIMED_INVOKE,
C.IS_FABRIC_SCOPED,
C.RESPONSE_REF,
C.RESPONSE_NAME,
C.IS_LARGE_MESSAGE
FROM COMMAND AS C
INNER JOIN CLUSTER AS CL
ON CL.CLUSTER_ID = C.CLUSTER_REF
WHERE
C.PACKAGE_REF = ?
AND C.CODE = ?
AND CL.CODE = ?`
let args
if (mfgCode == null || mfgCode == 0) {
query = query + ` AND C.MANUFACTURER_CODE IS NULL`
args = [packageId, commandCode, clusterCode]
} else {
query = query + ` AND C.MANUFACTURER_CODE = ?`
args = [packageId, commandCode, clusterCode, mfgCode]
}
return dbApi.dbGet(db, query, args).then(dbMapping.map.command)
}
/**
* Get global command by command code and package ID.
* @param {*} db
* @param {*} packageId
* @param {*} commandCode
* @param {*} mfgCode
* @returns Promise of command
*/
async function selectGlobalCommandByCode(
db,
packageId,
commandCode,
mfgCode = null
) {
let query = `
SELECT
C.COMMAND_ID,
C.CLUSTER_REF,
C.PACKAGE_REF,
C.CODE,
C.MANUFACTURER_CODE,
C.NAME,
C.DESCRIPTION,
C.SOURCE,
C.IS_OPTIONAL,
C.MUST_USE_TIMED_INVOKE,
C.IS_FABRIC_SCOPED,
C.RESPONSE_REF,
C.RESPONSE_NAME,
C.IS_LARGE_MESSAGE
FROM
COMMAND AS C
WHERE
C.PACKAGE_REF = ?
AND C.CODE = ?`
let args
if (mfgCode == null || mfgCode == 0) {
query = query + ` AND C.MANUFACTURER_CODE IS NULL`
args = [packageId, commandCode]
} else {
query = query + ` AND C.MANUFACTURER_CODE = ?`
args = [packageId, commandCode, mfgCode]
}
return dbApi.dbGet(db, query, args).then(dbMapping.map.command)
}
/**
* Get command by command ID.
* @param {*} db
* @param {*} id
* @returns Promise of command
*/
async function selectCommandById(db, id) {
return dbApi
.dbGet(
db,
`
SELECT
COMMAND_ID,
CLUSTER_REF,
PACKAGE_REF,
CODE,
MANUFACTURER_CODE,
NAME,
DESCRIPTION,
SOURCE,
IS_OPTIONAL,
MUST_USE_TIMED_INVOKE,
IS_FABRIC_SCOPED,
RESPONSE_REF,
RESPONSE_NAME
FROM COMMAND
WHERE COMMAND_ID = ?`,
[id]
)
.then(dbMapping.map.command)
}
/**
* Retrieves commands for a given cluster Id.
* This method DOES NOT retrieve global commands, since those have a cluster_ref = null
*
* @param {*} db
* @param {*} clusterId
* @returns promise of an array of command rows, which represent per-cluster commands, excluding global commands.
*/
async function selectCommandsByClusterId(db, clusterId, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.CLUSTER_REF,
COMMAND.CODE,
COMMAND.MANUFACTURER_CODE,
COMMAND.NAME,
COMMAND.DESCRIPTION,
COMMAND.SOURCE,
COMMAND.IS_OPTIONAL,
COMMAND.CONFORMANCE,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.IS_DEFAULT_RESPONSE_ENABLED,
COMMAND.IS_LARGE_MESSAGE,
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
ON
COMMAND.COMMAND_ID = COMMAND_ARG.COMMAND_REF
WHERE
CLUSTER_REF = ? AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
COMMAND.COMMAND_ID
ORDER BY CODE`,
[clusterId]
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Get all commands which have command arguments from the given package ID.
* @param {*} db
* @param {*} packageId
* @returns Promise of commands
*/
async function selectAllCommandsWithArguments(db, packageId) {
let mapFunction = (x) => {
return {
id: x.COMMAND_ID,
commandId: x.COMMAND_ID,
commandCode: x.CODE,
commandMfgCode: x.MANUFACTURER_CODE,
name: x.NAME,
commandName: x.NAME,
commandDescription: x.DESCRIPTION,
commandSource: x.SOURCE,
commandIsOptional: dbApi.fromDbBool(x.IS_OPTIONAL),
commandMustUseTimedInvoke: dbApi.fromDbBool(x.MUST_USE_TIMED_INVOKE),
commandIsFabricScoped: dbApi.fromDbBool(x.IS_FABRIC_SCOPED),
clusterName: x.CLUSTER_NAME,
clusterCode: x.CLUSTER_CODE,
clusterMfgCode: x.CLUSTER_MANUFACTURER_CODE,
argName: x.ARG_NAME,
argType: x.ARG_TYPE,
argMin: x.ARG_MIN,
argMax: x.ARG_MAX,
argMinLength: x.ARG_MIN_LENGTH,
argMaxLength: x.ARG_MAX_LENGTH,
argDefaultValue: x.ARG_DEFAULT_VALUE,
argFieldId: x.FIELD_IDENTIFIER,
argIsArray: dbApi.fromDbBool(x.ARG_IS_ARRAY),
argPresentIf: x.ARG_PRESENT_IF,
argIsNullable: dbApi.fromDbBool(x.ARG_IS_NULLABLE),
argCountArg: x.ARG_COUNT_ARG,
argIntroducedIn: x.INTRODUCED_IN_REF,
argRemovedIn: x.REMOVED_IN_REF,
isLargeMessage: dbApi.fromDbBool(x.IS_LARGE_MESSAGE)
}
}
let rows = await dbApi.dbAll(
db,
`
SELECT
CO.COMMAND_ID,
CO.CLUSTER_REF,
CO.CODE,
CO.MANUFACTURER_CODE,
CO.NAME,
CO.DESCRIPTION,
CO.SOURCE,
CO.IS_OPTIONAL,
CO.MUST_USE_TIMED_INVOKE,
CO.IS_FABRIC_SCOPED,
CO.RESPONSE_REF,
CO.RESPONSE_NAME,
CO.IS_LARGE_MESSAGE,
CL.NAME AS CLUSTER_NAME,
CL.CODE AS CLUSTER_CODE,
CL.MANUFACTURER_CODE AS CLUSTER_MANUFACTURER_CODE,
CA.NAME AS ARG_NAME,
CA.TYPE AS ARG_TYPE,
CA.MIN as ARG_MIN,
CA.MAX as ARG_MAX,
CA.MIN_LENGTH as ARG_MIN_LENGTH,
CA.MAX_LENGTH as ARG_MAX_LENGTH,
CA.DEFAULT_VALUE AS ARG_DEFAULT_VALUE,
CA.FIELD_IDENTIFIER,
CA.IS_ARRAY AS ARG_IS_ARRAY,
CA.PRESENT_IF AS ARG_PRESENT_IF,
CA.IS_NULLABLE AS ARG_IS_NULLABLE,
CA.COUNT_ARG AS ARG_COUNT_ARG,
CA.INTRODUCED_IN_REF,
CA.REMOVED_IN_REF
FROM
COMMAND AS CO
INNER JOIN
CLUSTER AS CL
ON
CL.CLUSTER_ID = CO.CLUSTER_REF
LEFT JOIN
COMMAND_ARG AS CA
ON
CA.COMMAND_REF = CO.COMMAND_ID
WHERE
CO.PACKAGE_REF = ?
ORDER BY
CL.CODE, CO.SOURCE, CO.CODE, CA.FIELD_IDENTIFIER`,
[packageId]
)
rows = rows.map(mapFunction)
let reduction = rows.reduce((total, current) => {
let lastItem = null
if (total.length > 0) lastItem = total[total.length - 1]
let extractArg = (x) => {
const ret = {
name: x.argName,
label: x.argName,
type: x.argType,
min: x.min,
max: x.max,
minLength: x.minLength,
maxLength: x.maxLength,
defaultValue: x.argDefaultValue,
fieldId: x.argFieldId,
isArray: x.argIsArray,
presentIf: x.argPresentIf,
isNullable: x.argIsNullable,
countArg: x.argCountArg,
introducedIn: x.argIntroducedIn,
removedIn: x.argRemovedIn,
introducedInRef: x.argIntroducedIn,
removedInRef: x.argRemovedIn
}
delete x.argName
delete x.argType
delete x.argMin
delete x.argMax
delete x.argMinLength
delete x.argMaxLength
delete x.argDefaultValue
delete x.argFieldId
delete x.argIsArray
delete x.argPresentIf
delete x.argIsNullable
delete x.argCountArg
delete x.argIntroducedIn
delete x.argRemovedIn
return ret
}
if (
lastItem == null ||
!(
lastItem.commandCode == current.commandCode &&
lastItem.commandMfgCode == current.commandMfgCode &&
lastItem.commandSource == current.commandSource &&
lastItem.clusterCode == current.clusterCode &&
lastItem.clusterMfgCode == current.clusterMfgCode
)
) {
// We have a new command
current.commandArgs = []
current.argCount = 0
if (current.argName != null) {
current.commandArgs.push(extractArg(current))
current.argCount++
}
total.push(current)
} else {
// We just aggregate args.
if (current.argName != null) {
lastItem.commandArgs.push(extractArg(current))
lastItem.argCount++
}
}
return total
}, [])
return reduction
}
/**
*
* @param db
* @param packageId
* @returns all commands along with their cluster information
*/
async function selectAllCommandsWithClusterInfo(db, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.CLUSTER_REF,
COMMAND.CODE,
COMMAND.MANUFACTURER_CODE,
COMMAND.NAME,
COMMAND.DESCRIPTION,
COMMAND.SOURCE,
COMMAND.IS_OPTIONAL,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CODE AS CLUSTER_CODE
FROM
COMMAND
INNER JOIN
CLUSTER
ON
CLUSTER.CLUSTER_ID = COMMAND.CLUSTER_REF
WHERE
COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
ORDER BY CLUSTER.CODE, COMMAND.CODE`
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Get all commands from the given package IDs
* @param {*} db
* @param {*} packageIds
* @returns Promise of commands
*/
async function selectAllCommands(db, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.CLUSTER_REF,
COMMAND.CODE,
COMMAND.MANUFACTURER_CODE,
COMMAND.NAME,
COMMAND.DESCRIPTION,
COMMAND.SOURCE,
COMMAND.IS_OPTIONAL,
COMMAND.CONFORMANCE,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.IS_DEFAULT_RESPONSE_ENABLED,
COMMAND.IS_LARGE_MESSAGE,
COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT
FROM
COMMAND
LEFT JOIN
COMMAND_ARG
ON
COMMAND.COMMAND_ID = COMMAND_ARG.COMMAND_REF
WHERE PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
COMMAND.COMMAND_ID
ORDER BY COMMAND.CODE, COMMAND.NAME`
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Get all commands by source(client/server) from the given package IDs.
* @param {*} db
* @param {*} source
* @param {*} packageIds
* @returns Promise of commands
*/
async function selectAllCommandsBySource(db, source, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND_ID,
CLUSTER_REF,
CODE,
MANUFACTURER_CODE,
NAME,
DESCRIPTION,
SOURCE,
IS_OPTIONAL,
MUST_USE_TIMED_INVOKE,
IS_FABRIC_SCOPED,
RESPONSE_REF,
RESPONSE_NAME
FROM
COMMAND
WHERE
SOURCE = ?
AND PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
ORDER BY CODE`,
[source]
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Retrieves filtered commands for a given cluster Id based on the source.
* This method DOES NOT retrieve global commands, since those have a cluster_ref = null
*
* @param {*} db
* @param {*} clusterId
* @param {*} source
* @param {*} packageIds
* @returns promise of an array of command rows, which represent per-cluster commands, excluding global commands.
*/
async function selectCommandsByClusterIdAndSource(
db,
clusterId,
source,
packageIds
) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND_ID,
CLUSTER_REF,
CODE,
MANUFACTURER_CODE,
NAME,
DESCRIPTION,
SOURCE,
IS_OPTIONAL,
MUST_USE_TIMED_INVOKE,
IS_FABRIC_SCOPED,
RESPONSE_NAME
FROM COMMAND
WHERE
CLUSTER_REF = ?
AND SOURCE = ?
AND PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
ORDER BY CODE`,
[clusterId, source]
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Get all global commands from given package IDs.
* @param {*} db
* @param {*} packageIds
* @returns Promise of global commands
*/
async function selectAllGlobalCommands(db, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.CLUSTER_REF,
COMMAND.CODE,
COMMAND.MANUFACTURER_CODE,
COMMAND.NAME,
COMMAND.DESCRIPTION,
COMMAND.SOURCE,
COMMAND.IS_OPTIONAL,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.IS_DEFAULT_RESPONSE_ENABLED,
COMMAND.IS_LARGE_MESSAGE,
COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT
FROM
COMMAND
LEFT JOIN
COMMAND_ARG
ON
COMMAND.COMMAND_ID = COMMAND_ARG.COMMAND_REF
WHERE
CLUSTER_REF IS NULL AND PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
COMMAND.COMMAND_ID
ORDER BY
CODE`,
[]
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Get all commands from the given package ID.
* @param {*} db
* @param {*} packageId
* @returns Promise of Commands
*/
async function selectAllClusterCommands(db, packageId) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND_ID,
CLUSTER_REF,
CODE,
MANUFACTURER_CODE,
NAME,
DESCRIPTION,
SOURCE,
IS_OPTIONAL,
MUST_USE_TIMED_INVOKE,
IS_FABRIC_SCOPED,
RESPONSE_REF,
RESPONSE_NAME
FROM
COMMAND
WHERE
CLUSTER_REF IS NOT NULL
AND PACKAGE_REF = ?
ORDER BY
CODE`,
[packageId]
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* Get all command arguments from the given package IDs.
* @param {*} db
* @param {*} packageIds
* @returns Promise of command arguments
*/
async function selectAllCommandArguments(db, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND_ARG.COMMAND_REF,
COMMAND_ARG.FIELD_IDENTIFIER,
COMMAND_ARG.NAME,
COMMAND_ARG.TYPE,
COMMAND_ARG.MIN,
COMMAND_ARG.MAX,
COMMAND_ARG.MIN_LENGTH,
COMMAND_ARG.MAX_LENGTH,
COMMAND_ARG.DEFAULT_VALUE,
COMMAND_ARG.IS_ARRAY,
COMMAND_ARG.PRESENT_IF,
COMMAND_ARG.IS_NULLABLE,
COMMAND_ARG.IS_OPTIONAL,
COMMAND_ARG.INTRODUCED_IN_REF,
COMMAND_ARG.REMOVED_IN_REF,
COMMAND_ARG.COUNT_ARG
FROM COMMAND_ARG, COMMAND
WHERE
COMMAND_ARG.COMMAND_REF = COMMAND.COMMAND_ID
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
ORDER BY COMMAND_REF, FIELD_IDENTIFIER`
)
.then((rows) => rows.map(dbMapping.map.commandArgument))
}
/**
* Get the number of command arguments for a command
*
* @param {*} db
* @param {*} commandId
* @returns A promise with number of command arguments for a command
*/
async function selectCommandArgumentsCountByCommandId(db, commandId) {
return dbApi
.dbAll(
db,
`
SELECT COUNT(*) AS count
FROM COMMAND_ARG WHERE COMMAND_REF = ? `,
[commandId]
)
.then((res) => res[0].count)
}
/**
* Extract the command arguments for a command
*
* @param {*} db
* @param {*} commandId
* @param {*} [packageId=null]
* @returns A promise with command arguments for a command
*/
async function selectCommandArgumentsByCommandId(db, commandId) {
return dbApi
.dbAll(
db,
`
SELECT
COMMAND_REF,
FIELD_IDENTIFIER,
NAME,
TYPE,
MIN,
MAX,
MIN_LENGTH,
MAX_LENGTH,
DEFAULT_VALUE,
IS_ARRAY,
PRESENT_IF,
IS_NULLABLE,
IS_OPTIONAL,
INTRODUCED_IN_REF,
REMOVED_IN_REF,
COUNT_ARG
FROM COMMAND_ARG
WHERE COMMAND_REF = ?
ORDER BY FIELD_IDENTIFIER`,
[commandId]
)
.then((rows) => rows.map(dbMapping.map.commandArgument))
}
/**
* This method returns all commands, joined with their
* respective arguments and clusters, so it's a long query.
* If you are just looking for a quick query across all commands
* use the selectAllCommands query.
*
* @param {*} db
* @param {*} packageIds
* @returns promise that resolves into a list of all commands and arguments.
*/
async function selectCommandTree(db, packageIds) {
return dbApi
.dbAll(
db,
`
SELECT
CMD.COMMAND_ID,
CMD.CLUSTER_REF,
CMD.CODE,
CMD.MANUFACTURER_CODE,
CMD.NAME,
CMD.DESCRIPTION,
CMD.SOURCE,
CMD.IS_OPTIONAL,
CMD.MUST_USE_TIMED_INVOKE,
CMD.IS_FABRIC_SCOPED,
CMD.RESPONSE_REF,
CMD.RESPONSE_NAME,
CMD.IS_LARGE_MESSAGE,
CL.CODE AS CLUSTER_CODE,
CL.NAME AS CLUSTER_NAME,
CL.NAME AS CLUSTER_NAME,
CL.DEFINE AS CLUSTER_DEFINE_NAME,
CA.NAME AS ARG_NAME,
CA.TYPE AS ARG_TYPE,
CA.MIN AS ARG_MIN,
CA.MAX AS ARG_MAX,
CA.MIN_LENGTH AS ARG_MIN_LENGTH,
CA.MAX_LENGTH AS ARG_MAX_LENGTH,
CA.DEFAULT_VALUE AS ARG_DEFAULT_VALUE,
CA.IS_ARRAY AS ARG_IS_ARRAY,
CA.PRESENT_IF AS ARG_PRESENT_IF,
CA.IS_NULLABLE AS ARG_IS_NULLABLE,
CA.COUNT_ARG AS ARG_COUNT_ARG
FROM
COMMAND AS CMD
LEFT JOIN
CLUSTER AS CL
ON
CMD.CLUSTER_REF = CL.CLUSTER_ID
LEFT JOIN
COMMAND_ARG AS CA
ON
CMD.COMMAND_ID = CA.COMMAND_REF
WHERE CMD.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
ORDER BY CL.CODE, CMD.CODE, CA.FIELD_IDENTIFIER`
)
.then((rows) => rows.map(dbMapping.map.command))
}
/**
* After the data is loaded from XML, we need to link the command request/responses
* RESPONSE_REF fields together using the RESPONSE_NAME.
*
* @param {*} db
*/
async function updateCommandRequestResponseReferences(db, packageId) {
// Link up all the cases where the RESPONSE_NAME is present
await dbApi.dbUpdate(
db,
`
UPDATE
COMMAND
SET
RESPONSE_REF =
( SELECT
CMD_REF.COMMAND_ID
FROM
COMMAND AS CMD_REF
WHERE
( CMD_REF.NAME = COMMAND.RESPONSE_NAME ) AND (
( CMD_REF.CLUSTER_REF = COMMAND.CLUSTER_REF )
OR
( CMD_REF.CLUSTER_REF IS NULL AND COMMAND.CLUSTER_REF IS NULL )
) AND (
( CMD_REF.PACKAGE_REF = COMMAND.PACKAGE_REF)
)
)
WHERE
COMMAND.RESPONSE_NAME IS NOT NULL
AND COMMAND.PACKAGE_REF = ?
`,
[packageId]
)
}
/**
* An exception for the command map in db-mapping.js
* @param {*} x
* @returns Command map
*/
function commandMapFunction(x) {
return {
id: x.COMMAND_ID,
name: x.NAME,
code: x.CODE,
commandSource: x.SOURCE,
source: x.SOURCE,
mustUseTimedInvoke: dbApi.fromDbBool(x.MUST_USE_TIMED_INVOKE),
isFabricScoped: dbApi.fromDbBool(x.IS_FABRIC_SCOPED),
mfgCode: x.MANUFACTURER_CODE,
incoming: x.INCOMING,
outgoing: x.OUTGOING,
isIncoming: x.IS_INCOMING,
isEnabled: x.COMMAND_ENABLED,
description: x.DESCRIPTION,
clusterSide: x.SIDE,
clusterId: x.CLUSTER_ID,
endpointClusterId: x.ENDPOINT_TYPE_CLUSTER_ID,
clusterName: x.CLUSTER_NAME,
clusterDefine: x.CLUSTER_DEFINE,
isClusterEnabled: x.ENABLED,
commandArgCount: x.COMMAND_ARGUMENT_COUNT,
responseRef: x.RESPONSE_REF,
responseName: x.RESPONSE_NAME,
isLargeMessage: dbApi.fromDbBool(x.IS_LARGE_MESSAGE)
}
}
/**
* Returns a promise of data for commands inside an endpoint type.
*
* @param {*} db
* @param {*} endpointTypeId
* @param {*} packageIds
* @returns Promise that resolves with the command data.
*/
async function selectAllCommandDetailsFromEnabledClusters(
db,
endpointsAndClusters,
packageIds
) {
let endpointTypeClusterRef = endpointsAndClusters
.map((ep) => ep.endpointTypeClusterRef)
.toString()
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.NAME,
COMMAND.CODE,
COMMAND.SOURCE,
COMMAND.MANUFACTURER_CODE,
COMMAND.DESCRIPTION,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
ENDPOINT_TYPE_CLUSTER.SIDE,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.CLUSTER_ID,
ENDPOINT_TYPE_CLUSTER.ENABLED,
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
FROM
COMMAND
INNER JOIN
CLUSTER
ON
COMMAND.CLUSTER_REF = CLUSTER.CLUSTER_ID
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
CLUSTER.CLUSTER_ID = ENDPOINT_TYPE_CLUSTER.CLUSTER_REF
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID IN (${endpointTypeClusterRef})
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY
COMMAND.NAME
`
)
.then((rows) => rows.map(commandMapFunction))
}
/**
*
* @param db
* @param endpointsAndClusters
* @param packageIds
* @returns Returns a promise of data for commands with cli inside an endpoint type.
*/
async function selectAllCliCommandDetailsFromEnabledClusters(
db,
endpointsAndClusters,
packageIds
) {
let endpointTypeClusterRef = endpointsAndClusters
.map((ep) => ep.endpointTypeClusterRef)
.toString()
return dbApi
.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.NAME,
COMMAND.CODE,
COMMAND.SOURCE,
COMMAND.MANUFACTURER_CODE,
COMMAND.DESCRIPTION,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
ENDPOINT_TYPE_CLUSTER.SIDE,
CLUSTER.NAME AS CLUSTER_NAME,
CLUSTER.DEFINE AS CLUSTER_DEFINE,
ENDPOINT_TYPE_CLUSTER.ENABLED,
COUNT(COMMAND_ARG.COMMAND_REF) AS COMMAND_ARGUMENT_COUNT
FROM COMMAND
LEFT JOIN
COMMAND_ARG
ON
COMMAND_ARG.COMMAND_REF = COMMAND.COMMAND_ID
INNER JOIN CLUSTER
ON COMMAND.CLUSTER_REF = CLUSTER.CLUSTER_ID
INNER JOIN ENDPOINT_TYPE_CLUSTER
ON CLUSTER.CLUSTER_ID = ENDPOINT_TYPE_CLUSTER.CLUSTER_REF
INNER JOIN PACKAGE_OPTION
ON PACKAGE_OPTION.OPTION_CODE = COMMAND.NAME
WHERE ENDPOINT_TYPE_CLUSTER.CLUSTER_REF IN (${endpointTypeClusterRef}) AND ENDPOINT_TYPE_CLUSTER.ENABLED=1
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY COMMAND.NAME, CLUSTER.NAME
`
)
.then((rows) => rows.map(commandMapFunction))
}
/**
* Returns a promise of data for commands inside an endpoint type.
*
* @param {*} db
* @param {*} endpointTypeId
* @param {*} doGroupBy
* @param {*} packageIds
* @returns Promise that resolves with the command data.
*/
async function selectCommandDetailsFromAllEndpointTypesAndClusters(
db,
endpointsAndClusters,
doGroupBy,
packageIds
) {
let endpointTypeIds = endpointsAndClusters
.map((ep) => ep.endpointId)
.toString()
let endpointClusterIds = endpointsAndClusters
.map((ep) => ep.endpointClusterId)
.toString()
let query = `
SELECT
C.COMMAND_ID,
C.NAME,
C.CODE,
C.SOURCE,
C.MANUFACTURER_CODE,
C.DESCRIPTION,
C.RESPONSE_REF,
C.RESPONSE_NAME,
C.MUST_USE_TIMED_INVOKE,
C.IS_FABRIC_SCOPED,
C.IS_LARGE_MESSAGE,
CASE
WHEN
(COUNT(CASE WHEN ETC.IS_INCOMING=1 AND ETC.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY C.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS INCOMING,
CASE
WHEN
(COUNT(CASE WHEN ETC.IS_INCOMING=0 AND ETC.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY C.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS OUTGOING,
ETCL.SIDE,
ETCL.ENABLED,
CLUSTER.NAME AS CLUSTER_NAME
FROM
COMMAND AS C
INNER JOIN
ENDPOINT_TYPE_COMMAND AS ETC
ON
C.COMMAND_ID = ETC.COMMAND_REF
INNER JOIN
ENDPOINT_TYPE_CLUSTER AS ETCL
ON
ETC.ENDPOINT_TYPE_CLUSTER_REF = ETCL.ENDPOINT_TYPE_CLUSTER_ID
INNER JOIN
CLUSTER
ON
C.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE
ETCL.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ETC.ENDPOINT_TYPE_CLUSTER_REF in (${endpointClusterIds})
AND C.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})`
if (doGroupBy) {
// See: https://github.com/project-chip/zap/issues/192
query = 'SELECT * FROM (' + query + ') GROUP BY NAME, COMMAND_ID'
}
// Ordering of the results:
query = query + ' ORDER BY MANUFACTURER_CODE, CODE, NAME'
return dbApi.dbAll(db, query).then((rows) => rows.map(commandMapFunction))
}
/**
* Returns a promise of data for manufacturing/non-manufacturing specific commands
* inside an endpoint type.
*
* @param db
* @param endpointTypeId
* @param isManufacturingSpecific
* @param packageIds
* @returns Promise that resolves with the manufacturing/non-manufacturing
* specific command data.
*/
async function selectCommandDetailsFromAllEndpointTypesAndClustersUtil(
db,
endpointsAndClusters,
isManufacturingSpecific,
packageIds
) {
let endpointTypeIds = endpointsAndClusters
.map((ep) => ep.endpointId)
.toString()
let endpointClusterIds = endpointsAndClusters
.map((ep) => ep.endpointClusterId)
.toString()
return dbApi
.dbAll(
db,
`
SELECT * FROM (
SELECT
COMMAND.COMMAND_ID,
COMMAND.NAME,
COMMAND.CODE,
COMMAND.SOURCE,
COMMAND.MANUFACTURER_CODE,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=1 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS INCOMING,
CASE
WHEN
(COUNT(CASE WHEN ENDPOINT_TYPE_COMMAND.IS_INCOMING=0 AND ENDPOINT_TYPE_COMMAND.IS_ENABLED THEN 1 ELSE NULL END) OVER (PARTITION BY COMMAND.COMMAND_ID)) >= 1
THEN
1
ELSE
0
END AS OUTGOING,
COMMAND.DESCRIPTION,
COMMAND.RESPONSE_REF,
COMMAND.RESPONSE_NAME,
COMMAND.MUST_USE_TIMED_INVOKE,
COMMAND.IS_FABRIC_SCOPED,
ENDPOINT_TYPE_CLUSTER.SIDE,
CLUSTER.NAME AS CLUSTER_NAME,
ENDPOINT_TYPE_CLUSTER.ENABLED
FROM
COMMAND
INNER JOIN
ENDPOINT_TYPE_COMMAND
ON
COMMAND.COMMAND_ID = ENDPOINT_TYPE_COMMAND.COMMAND_REF
INNER JOIN
ENDPOINT_TYPE_CLUSTER
ON
ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF = ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
INNER JOIN
CLUSTER
ON
COMMAND.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_REF IN (${endpointTypeIds})
AND ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF in (${endpointClusterIds})
AND COMMAND.MANUFACTURER_CODE IS ${
isManufacturingSpecific ? `NOT` : ``
} NULL
AND COMMAND.PACKAGE_REF IN (${dbApi.toInClause(packageIds)}))
GROUP BY NAME
`
)
.then((rows) => rows.map(commandMapFunction))
}
/**
* Returns a promise of data for manufacturing specific commands inside an endpoint type.
*
* @param db
* @param endpointTypeId
* @param packageIds
* @returns Promise that resolves with the manufacturing specific command data.
*/
async function selectManufacturerSpecificCommandDetailsFromAllEndpointTypesAndClusters(
db,
endpointsAndClusters,
packageIds
) {
return selectCommandDetailsFromAllEndpointTypesAndClustersUtil(
db,
endpointsAndClusters,
true,
packageIds
)
}
/**
* Returns a promise of data for commands with no manufacturing specific information inside an endpoint type.
*
* @param db
* @param endpointTypeId
* @param packageIds
* @returns Promise that resolves with the non-manufacturing specific command data.
*/
async function selectNonManufacturerSpecificCommandDetailsFromAllEndpointTypesAndClusters(
db,
endpointsAndClusters,
packageIds
) {
return selectCommandDetailsFromAllEndpointTypesAndClustersUtil(
db,
endpointsAndClusters,
false,
packageIds
)
}
/**
* Get all commands in an endpoint type cluster
* @param {*} db
* @param {*} endpointTypeClusterId
* @returns all commands in an endpoint type cluster
*/
async function selectCommandsByEndpointTypeClusterId(
db,
endpointTypeClusterId
) {
let rows = await dbApi.dbAll(
db,
`
SELECT
COMMAND.COMMAND_ID,
COMMAND.NAME,
COMMAND.CLUSTER_REF,
COMMAND.SOURCE,
COMMAND.CONFORMANCE,
COALESCE(ENDPOINT_TYPE_COMMAND.IS_ENABLED, 0) AS IS_ENABLED
FROM
COMMAND
JOIN
ENDPOINT_TYPE_CLUSTER
ON
COMMAND.CLUSTER_REF = ENDPOINT_TYPE_CLUSTER.CLUSTER_REF
AND
ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID = ?
LEFT JOIN
ENDPOINT_TYPE_COMMAND
ON
COMMAND.COMMAND_ID = ENDPOINT_TYPE_COMMAND.COMMAND_REF
AND
ENDPOINT_TYPE_COMMAND.ENDPOINT_TYPE_CLUSTER_REF = ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
`,
[endpointTypeClusterId]
)
return rows.map(dbMapping.map.endpointTypeCommandExtended)
}
exports.selectCliCommandCountFromEndpointTypeCluster =
selectCliCommandCountFromEndpointTypeCluster
exports.selectCliCommandsFromCluster = selectCliCommandsFromCluster
exports.selectAllAvailableClusterCommandDetailsFromEndpointTypes =
selectAllAvailableClusterCommandDetailsFromEndpointTypes
exports.selectAllClustersWithIncomingCommands =
selectAllClustersWithIncomingCommands
exports.selectAllClustersWithIncomingCommandsCombined =
selectAllClustersWithIncomingCommandsCombined
exports.selectAllIncomingCommandsForCluster =
selectAllIncomingCommandsForCluster
exports.selectAllIncomingCommandsForClusterCombined =
selectAllIncomingCommandsForClusterCombined
exports.selectAllCommands = selectAllCommands
exports.selectCommandsByClusterId = selectCommandsByClusterId
exports.selectCommandById = selectCommandById
exports.selectCommandByCode = selectCommandByCode
exports.selectAllCommandsBySource = selectAllCommandsBySource
exports.selectCommandsByClusterIdAndSource = selectCommandsByClusterIdAndSource
exports.selectAllGlobalCommands = selectAllGlobalCommands
exports.selectAllClusterCommands = selectAllClusterCommands
exports.selectAllCommandArguments = selectAllCommandArguments
exports.selectCommandArgumentsCountByCommandId =
selectCommandArgumentsCountByCommandId
exports.selectCommandArgumentsByCommandId = selectCommandArgumentsByCommandId
exports.selectCommandTree = selectCommandTree
exports.updateCommandRequestResponseReferences =
updateCommandRequestResponseReferences
exports.selectAllCommandDetailsFromEnabledClusters =
selectAllCommandDetailsFromEnabledClusters
exports.selectAllCliCommandDetailsFromEnabledClusters =
selectAllCliCommandDetailsFromEnabledClusters
exports.selectCommandDetailsFromAllEndpointTypesAndClusters =
selectCommandDetailsFromAllEndpointTypesAndClusters
exports.selectManufacturerSpecificCommandDetailsFromAllEndpointTypesAndClusters =
selectManufacturerSpecificCommandDetailsFromAllEndpointTypesAndClusters
exports.selectNonManufacturerSpecificCommandDetailsFromAllEndpointTypesAndClusters =
selectNonManufacturerSpecificCommandDetailsFromAllEndpointTypesAndClusters
exports.selectAllIncomingCommands = selectAllIncomingCommands
exports.selectMfgClustersWithIncomingCommandsForClusterCode =
selectMfgClustersWithIncomingCommandsForClusterCode
exports.selectAllCommandsWithClusterInfo = selectAllCommandsWithClusterInfo
exports.selectAllCommandsWithArguments = selectAllCommandsWithArguments
exports.selectAllClustersWithOutgoingCommands =
selectAllClustersWithOutgoingCommands
exports.selectAllOutgoingCommandsForCluster =
selectAllOutgoingCommandsForCluster
exports.selectEndpointTypeCommandsByEndpointTypeRefAndClusterRef =
selectEndpointTypeCommandsByEndpointTypeRefAndClusterRef
exports.duplicateEndpointTypeCommand = duplicateEndpointTypeCommand
exports.selectCommandsByEndpointTypeClusterId =
selectCommandsByEndpointTypeClusterId