Skip to content

Commit

Permalink
Adding to enabled_attributes_for_cluster_and_side and zcl_attributes_…
Browse files Browse the repository at this point in the history
…server helper to replace chip_server_cluster_attributes (#899)

- chip_server_cluster_attributes is returning server attributes which are not actually enabled because the server side cluster is disabled.
- The reason chip_server_cluster_attributes is picking the server side attributes which are not enabled is because those are enabled in the .zap file(Which is the case for saving user selections and ease of use). However the helper is not actually checking if the cluster is enabled as well.
- enabled_attributes_for_cluster_and_side is solving this issue correctly and actually only showing attributes which are truly enabled.
- Extending endpointTypeAttributeExtended such that there is a common place for an attribute map
- Updating endpointTypeAttributeExtended with everything that attributeExportMapping had such that it can act as a common place for all other temporary maps that have been created across our code. Also sorting endpointTypeAttributeExtended for easier readability and avoiding duplicate keys
- Updating zcl_attributes_server block helper such that it can behave like chip_server_cluster_attributes.
- Updating attribute map such that it can be used more widely
- Adding additional helpers to remove the stateful helpers
- Adding removeKeys option for removing certain columns which are not needed in a block helper such as enabled_attributes_for_cluster_and_side and zcl_attributes_server
- Adding if_unsupported_attribute_type and if_attribute_complex to check for unsupported and complex zcl data types
- Deprecating old stateful helpers with new stateless helpers
- Adding select data type using type name and cluster id to data_types, enums, bitmap,  numbers and structs
- Adding if_unsupported_attribute_callback helper and if_basic_attribute if helpers for java code generation
- Deprecating java and python zcl type helpers with new zcl type helpers such that they do not need any stateful information coming from parent block helpers. For eg chipType and chipCallback.type
- Adding tests for all the newly introduced helpers.
- Updating Api documentation
- Adding if_is_data_type_signed and as_zcl_data_type_size to determine sign and size of zcl data types
- if_is_data_type_signed and as_zcl_data_type_size take type name and cluster id to return size and sign of the zcl data types
- Github: ZAP#898
  • Loading branch information
brdandu authored Mar 16, 2023
1 parent f630679 commit feb352c
Show file tree
Hide file tree
Showing 20 changed files with 2,251 additions and 397 deletions.
1,593 changes: 1,282 additions & 311 deletions docs/api.md

Large diffs are not rendered by default.

77 changes: 54 additions & 23 deletions src-electron/db/db-mapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

const dbApi = require('./db-api.js')
const dbEnums = require('../../src-shared/db-enum.js')
const bin = require('../util/bin')

exports.map = {
package: (x) => {
Expand Down Expand Up @@ -93,7 +94,7 @@ exports.map = {
manufacturerCode: x.MANUFACTURER_CODE,
name: x.NAME,
label: x.NAME,
type: x.TYPE,
type: x.TYPE != 'array' ? x.TYPE : x.ARRAY_TYPE,
side: x.SIDE,
define: x.DEFINE,
min: x.MIN,
Expand All @@ -105,15 +106,20 @@ exports.map = {
reportableChange: x.REPORTABLE_CHANGE,
reportableChangeLength: x.REPORTABLE_CHANGE_LENGTH,
isWritable: dbApi.fromDbBool(x.IS_WRITABLE),
isWritableAttribute: dbApi.fromDbBool(x.IS_WRITABLE),
isNullable: dbApi.fromDbBool(x.IS_NULLABLE),
defaultValue: x.DEFAULT_VALUE,
isOptional: dbApi.fromDbBool(x.IS_OPTIONAL),
isReportable:
x.REPORTING_POLICY == dbEnums.reportingPolicy.mandatory ||
x.REPORTING_POLICY == dbEnums.reportingPolicy.suggested,
isReportableAttribute:
x.REPORTING_POLICY == dbEnums.reportingPolicy.mandatory ||
x.REPORTING_POLICY == dbEnums.reportingPolicy.suggested,
reportingPolicy: x.REPORTING_POLICY,
isSceneRequired: dbApi.fromDbBool(x.IS_SCENE_REQUIRED),
entryType: x.ARRAY_TYPE,
isArray: x.ARRAY_TYPE ? 1 : 0,
mustUseTimedWrite: dbApi.fromDbBool(x.MUST_USE_TIMED_WRITE),
}
},
Expand Down Expand Up @@ -475,36 +481,61 @@ exports.map = {
endpointTypeAttributeExtended: (x) => {
if (x == null) return undefined
return {
endpointTypeRef: x.ENDPOINT_TYPE_REF,
clusterRef: x.CLUSTER_REF,
arrayType: x.ARRAY_TYPE,
attributeRef: x.ATTRIBUTE_REF,
included: dbApi.fromDbBool(x.INCLUDED),
storageOption: x.STORAGE_OPTION,
singleton: dbApi.fromDbBool(x.SINGLETON),
bounded: dbApi.fromDbBool(x.BOUNDED),
defaultValue: x.DEFAULT_VALUE,
includedReportable: dbApi.fromDbBool(x.INCLUDED_REPORTABLE),
minInterval: x.MIN_INTERVAL,
maxInterval: x.MAX_INTERVAL,
reportableChange: x.REPORTABLE_CHANGE,
name: x.NAME, // Attribute Name
code: x.CODE, // Attribute Code
side: x.SIDE, // Attribute Side
define: x.DEFINE, // Attribute define
type: x.TYPE, // Attribute type
mfgCode: x.MANUFACTURER_CODE
? x.MANUFACTURER_CODE
: x.CLUSTER_MANUFACTURER_CODE, // Attribute manufacturer code
clusterDefine: x.CLUSTER_DEFINE,
clusterMfgCode: x.CLUSTER_MANUFACTURER_CODE,
clusterName: x.CLUSTER_NAME,
clusterDefine: x.CLUSTER_DEFINE,
isSingleton: dbApi.fromDbBool(x.SINGLETON), // Endpoint type attribute is singleton or not
clusterRef: x.CLUSTER_REF,
clusterSide: x.SIDE,
code: x.CODE, // Attribute Code
defaultValue: x.DEFAULT_VALUE,
define: x.DEFINE, // Attribute define
endpointId: x.ENDPOINT_IDENTIFIER, // Endpoint type attribute's endpoint Id
endpointTypeRef: x.ENDPOINT_TYPE_REF,
entryType: x.ARRAY_TYPE,
hexCode: '0x' + bin.int16ToHex(x['CODE'] ? x['CODE'] : 0), // Attribute code in hex
id: x.ATTRIBUTE_ID, // Attribute id
included: dbApi.fromDbBool(x.INCLUDED),
includedReportable: dbApi.fromDbBool(x.INCLUDED_REPORTABLE), // Is attribute reportable
isArray: x.IS_ARRAY, // Is attribute of type array
isBound: dbApi.fromDbBool(x.BOUNDED), // Is endpoint type attribute bounded
isClusterEnabled: x.ENABLED,
isGlobalAttribute: x.IS_GLOBAL_ATTRIBUTE, // Is attribute global
isIncluded: dbApi.fromDbBool(x.INCLUDED), // Is endpoint type attribute included
isManufacturingSpecific: dbApi.toDbBool(
x.MANUFACTURER_CODE | x.CLUSTER_MANUFACTURER_CODE
), // Is Attribute mfg specific or not
endpointId: x.ENDPOINT_IDENTIFIER, // Endpoint type attribute's endpoint Id
tokenId: x.TOKEN_ID, // Endpoint type attribute's token id
isNullable: dbApi.fromDbBool(x.IS_NULLABLE), // Is attribute nullable
isOptionalAttribute: dbApi.fromDbBool(x.IS_OPTIONAL),
isReportableAttribute: dbApi.fromDbBool(x.INCLUDED_REPORTABLE), // Is attribute reportable
isSceneRequired: dbApi.fromDbBool(x.IS_SCENE_REQUIRED),
isSingleton: dbApi.fromDbBool(x.SINGLETON), // Endpoint type attribute is singleton or not
isWritable: dbApi.fromDbBool(x.IS_WRITABLE), // Is attribute writable
isWritableAttribute: dbApi.fromDbBool(x.IS_WRITABLE), // Is attribute writable
manufacturerCode: x.MANUFACTURER_CODE
? x.MANUFACTURER_CODE
: x.CLUSTER_MANUFACTURER_CODE, // Attribute manufacturer code
max: x.MAX, // Attribute max value
maxInterval: x.MAX_INTERVAL,
maxLength: x.MAX_LENGTH, // Attribute max length
mfgCode: x.MANUFACTURER_CODE
? x.MANUFACTURER_CODE
: x.CLUSTER_MANUFACTURER_CODE, // Attribute manufacturer code
min: x.MIN, // Attribute min value
minInterval: x.MIN_INTERVAL,
minLength: x.MIN_LENGTH, // Attribute min length
mustUseTimedWrite: dbApi.fromDbBool(x.MUST_USE_TIMED_WRITE),
name: x.NAME, // Attribute Name
reportableChange: x.REPORTABLE_CHANGE,
side: x.SIDE, // Attribute Side
singleton: dbApi.fromDbBool(x.SINGLETON),
smallestEndpointIdentifier: x.SMALLEST_ENDPOINT_IDENTIFIER, // Smallest endpoint Id in which the attribute is present
storage: x.STORAGE_OPTION,
storageOption: x.STORAGE_OPTION,
tokenId: x.TOKEN_ID, // Endpoint type attribute's token id
type: x.TYPE != 'array' ? x.TYPE : x.ARRAY_TYPE, // Attribute type
}
},

Expand Down
77 changes: 53 additions & 24 deletions src-electron/db/query-attribute.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,6 @@ const dbApi = require('./db-api.js')
const dbMapping = require('./db-mapping.js')
const dbCache = require('./db-cache')

function attributeExportMapping(x) {
return {
id: x.ATTRIBUTE_ID,
name: x.NAME,
code: x.CODE,
side: x.SIDE,
type: x.TYPE,
define: x.DEFINE,
mfgCode: x.MANUFACTURER_CODE,
clusterSide: x.SIDE,
clusterName: x.CLUSTER_NAME,
isClusterEnabled: x.ENABLED,
}
}

/**
* Promises to select all endpoint type attributes filtered by EndpointTypeRef and ClusterRef.
*
Expand Down Expand Up @@ -147,13 +132,19 @@ async function duplicateEndpointTypeAttribute(
* @param {*} db
* @param {*} endpointTypeId
* @param {*} packageIds
* @param {*} side
* @returns Promise that resolves with the attribute data.
*/
async function selectAllAttributeDetailsFromEnabledClusters(
db,
endpointsAndClusters,
packageIds
packageIds,
side = null
) {
let sideFilter = ''
if (side) {
sideFilter = ` AND ATTRIBUTE.SIDE = '${side}' `
}
let endpointTypeClusterRef = endpointsAndClusters
.map((ep) => ep.endpointTypeClusterRef)
.toString()
Expand All @@ -171,21 +162,59 @@ async function selectAllAttributeDetailsFromEnabledClusters(
ATTRIBUTE.MANUFACTURER_CODE,
ENDPOINT_TYPE_CLUSTER.SIDE,
CLUSTER.NAME AS CLUSTER_NAME,
ENDPOINT_TYPE_CLUSTER.ENABLED
ENDPOINT_TYPE_CLUSTER.ENABLED,
CASE
WHEN
ATTRIBUTE.ARRAY_TYPE IS NOT NULL
THEN
1
ELSE
0
END AS IS_ARRAY,
ATTRIBUTE.IS_WRITABLE,
ATTRIBUTE.IS_NULLABLE,
ATTRIBUTE.MAX_LENGTH,
ATTRIBUTE.MIN_LENGTH,
ATTRIBUTE.MIN,
ATTRIBUTE.MAX,
ATTRIBUTE.ARRAY_TYPE,
ATTRIBUTE.MUST_USE_TIMED_WRITE,
ATTRIBUTE.IS_SCENE_REQUIRED,
ATTRIBUTE.IS_OPTIONAL,
CASE
WHEN
ATTRIBUTE.CLUSTER_REF IS NULL
THEN
1
ELSE
0
END AS IS_GLOBAL_ATTRIBUTE,
ENDPOINT_TYPE_ATTRIBUTE.INCLUDED_REPORTABLE,
ENDPOINT_TYPE_ATTRIBUTE.STORAGE_OPTION,
ENDPOINT_TYPE_ATTRIBUTE.SINGLETON,
ENDPOINT_TYPE_ATTRIBUTE.BOUNDED,
ENDPOINT_TYPE_ATTRIBUTE.INCLUDED,
ENDPOINT_TYPE_ATTRIBUTE.DEFAULT_VALUE,
ENDPOINT_TYPE_ATTRIBUTE.MIN_INTERVAL,
ENDPOINT_TYPE_ATTRIBUTE.MAX_INTERVAL,
ENDPOINT_TYPE_ATTRIBUTE.REPORTABLE_CHANGE
FROM ATTRIBUTE
INNER JOIN ENDPOINT_TYPE_ATTRIBUTE
ON ATTRIBUTE.ATTRIBUTE_ID = ENDPOINT_TYPE_ATTRIBUTE.ATTRIBUTE_REF
INNER JOIN CLUSTER
ON ATTRIBUTE.CLUSTER_REF = CLUSTER.CLUSTER_ID
INNER JOIN ENDPOINT_TYPE_CLUSTER
ON CLUSTER.CLUSTER_ID = ENDPOINT_TYPE_CLUSTER.CLUSTER_REF
ON ENDPOINT_TYPE_ATTRIBUTE.ENDPOINT_TYPE_CLUSTER_REF = ENDPOINT_TYPE_CLUSTER.ENDPOINT_TYPE_CLUSTER_ID
INNER JOIN CLUSTER
ON ENDPOINT_TYPE_CLUSTER.CLUSTER_REF = CLUSTER.CLUSTER_ID
WHERE ENDPOINT_TYPE_CLUSTER.CLUSTER_REF IN (${endpointTypeClusterRef})
AND ENDPOINT_TYPE_ATTRIBUTE.INCLUDED = 1
AND ATTRIBUTE.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
GROUP BY ATTRIBUTE.NAME
AND ENDPOINT_TYPE_CLUSTER.ENABLED = 1
AND ATTRIBUTE.PACKAGE_REF IN (${dbApi.toInClause(packageIds)})
${sideFilter}
GROUP BY CLUSTER.MANUFACTURER_CODE, CLUSTER.CODE, ATTRIBUTE.MANUFACTURER_CODE, ATTRIBUTE.CODE, ATTRIBUTE.SIDE
ORDER BY ATTRIBUTE.CODE
`
)
.then((rows) => rows.map(attributeExportMapping))
.then((rows) => rows.map(dbMapping.map.endpointTypeAttributeExtended))
}

/**
Expand Down Expand Up @@ -248,7 +277,7 @@ async function selectAttributeDetailsFromAllEndpointTypesAndClustersUtil(
GROUP BY ATTRIBUTE.NAME
`
)
.then((rows) => rows.map(attributeExportMapping))
.then((rows) => rows.map(dbMapping.map.endpointTypeAttributeExtended))
}

/**
Expand Down
37 changes: 37 additions & 0 deletions src-electron/db/query-bitmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
const dbApi = require('./db-api')
const dbCache = require('./db-cache')
const dbMapping = require('./db-mapping')
const queryUtil = require('./query-util')

/**
* Retrieves all the bitmaps in the database.
Expand Down Expand Up @@ -68,6 +69,39 @@ WHERE (DATA_TYPE.NAME = ? OR DATA_TYPE.NAME = ?) AND DATA_TYPE.PACKAGE_REF IN ($
.then(dbMapping.map.bitmap)
}

/**
* Select a bitmap matched by name and clusterId.
* @param {*} db
* @param {*} name
* @param {*} clusterId
* @param {*} packageIds
* @returns bitmap information or undefined
*/
async function selectBitmapByNameAndClusterId(db, name, clusterId, packageIds) {
let queryWithoutClusterId = queryUtil.sqlQueryForDataTypeByNameAndClusterId(
'bitmap',
null,
packageIds
)
let queryWithClusterId = queryUtil.sqlQueryForDataTypeByNameAndClusterId(
'bitmap',
clusterId,
packageIds
)

let res = await dbApi
.dbAll(db, queryWithoutClusterId, [name, name.toLowerCase()])
.then((rows) => rows.map(dbMapping.map.bitmap))

if (res && res.length == 1) {
return res[0]
} else {
return dbApi
.dbGet(db, queryWithClusterId, [name, name.toLowerCase(), clusterId])
.then(dbMapping.map.bitmap)
}
}

async function selectBitmapById(db, id) {
return dbApi
.dbGet(
Expand All @@ -88,3 +122,6 @@ WHERE BITMAP_ID = ?`,
exports.selectBitmapById = selectBitmapById
exports.selectAllBitmaps = selectAllBitmaps
exports.selectBitmapByName = dbCache.cacheQuery(selectBitmapByName)
exports.selectBitmapByNameAndClusterId = dbCache.cacheQuery(
selectBitmapByNameAndClusterId
)
68 changes: 68 additions & 0 deletions src-electron/db/query-data-type.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,71 @@ async function selectDataTypeByName(db, name, packageIds) {
.then(dbMapping.map.dataType)
}

/**
* Gathers the data type information based on data type name and
* clusterId along with its actual type from disciminator table.
* @param db
* @param name
* @param clusterId
* @param packageIds
* @returns Data type information
*/
async function selectDataTypeByNameAndClusterId(
db,
name,
clusterId,
packageIds
) {
let selectQueryString = `
SELECT
DATA_TYPE.DATA_TYPE_ID,
DATA_TYPE.NAME AS NAME,
DATA_TYPE.DESCRIPTION,
DATA_TYPE.DISCRIMINATOR_REF,
DATA_TYPE.PACKAGE_REF,
DISCRIMINATOR.NAME AS DISCRIMINATOR_NAME
FROM
DATA_TYPE
INNER JOIN
DISCRIMINATOR
ON
DATA_TYPE.DISCRIMINATOR_REF = DISCRIMINATOR.DISCRIMINATOR_ID `

let clusterQueryExtension = `
INNER JOIN
DATA_TYPE_CLUSTER
ON
DATA_TYPE.DATA_TYPE_ID = DATA_TYPE_CLUSTER.DATA_TYPE_REF `

let whereClause = `
WHERE
(DATA_TYPE.NAME = ? OR DATA_TYPE.NAME = ?)
AND DATA_TYPE.PACKAGE_REF IN (${dbApi.toInClause(packageIds)}) `

let whereClauseClusterExtension = `
AND DATA_TYPE_CLUSTER.CLUSTER_REF = ?`

let queryWithoutClusterId = selectQueryString + whereClause
let queryWithClusterId =
selectQueryString +
clusterQueryExtension +
whereClause +
whereClauseClusterExtension

let smallCaseName = name.toLowerCase()
let res = await dbApi
.dbAll(db, queryWithoutClusterId, [name, smallCaseName])
.then((rows) => rows.map(dbMapping.map.dataType))

if (res && res.length == 1) {
return res[0]
} else {
return dbApi
.dbGet(db, queryWithClusterId, [name, smallCaseName, clusterId])
.then(dbMapping.map.dataType)
}
}

/**
* Gathers All the data types
* @param db
Expand Down Expand Up @@ -186,3 +251,6 @@ exports.selectDataTypeById = selectDataTypeById
exports.selectDataTypeByName = dbCache.cacheQuery(selectDataTypeByName)
exports.selectAllDataTypes = selectAllDataTypes
exports.selectSizeFromType = selectSizeFromType
exports.selectDataTypeByNameAndClusterId = dbCache.cacheQuery(
selectDataTypeByNameAndClusterId
)
Loading

0 comments on commit feb352c

Please sign in to comment.