Skip to content

Commit

Permalink
Custom type phase 1 (#1333)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulr34 authored Jun 6, 2024
1 parent 1cc9343 commit 1bf40e8
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 36 deletions.
21 changes: 21 additions & 0 deletions src-electron/db/query-atomic.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,27 @@ async function selectAtomicById(db, id) {
.then((rows) => rows.map(dbMapping.map.atomic))
}

/**
* Checks if a type by a given name is signed.
*
* @param {object} db - The database connection object.
* @param {string} name - The name of the type.
* @param {Array} sessionPackages - An array of session packages.
* @returns {Promise<boolean>} - A promise that resolves to true if the type is signed, false otherwise.
*/
async function isTypeSignedByNameAndPackage(db, name, sessionPackages) {
const sessionPackage = sessionPackages[0].packageRef
const row = await dbApi.dbGet(
db,
`SELECT IS_SIGNED FROM ATOMIC WHERE NAME = ? AND PACKAGE_REF = ?`,
[name, sessionPackage]
)

return row ? row.IS_SIGNED === 1 : false
}

// exports
exports.isTypeSignedByNameAndPackage = isTypeSignedByNameAndPackage
exports.selectAllAtomics = selectAllAtomics
exports.selectAtomicType = dbCache.cacheQuery(selectAtomicType)
exports.selectAtomicById = selectAtomicById
2 changes: 1 addition & 1 deletion src-electron/db/query-zcl.js
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ ORDER BY
return rows.map(dbMapping.map.endpointTypeEvent)
}

// exports
//exports
exports.selectClusterBitmaps = selectClusterBitmaps
exports.selectAllBitmapFields = selectAllBitmapFields
exports.selectAllBitmapFieldsById = selectAllBitmapFieldsById
Expand Down
30 changes: 17 additions & 13 deletions src-electron/generator/helper-endpointconfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,11 +645,13 @@ function asMEI(manufacturerCode, code) {

// The representation of null depends on the type, so we can't use a single
// macro that's defined elsewhere for "null value".
function determineAttributeDefaultValue(
async function determineAttributeDefaultValue(
specifiedDefault,
type,
typeSize,
isNullable
isNullable,
db,
sessionId
) {
if (specifiedDefault !== null || !isNullable) {
return specifiedDefault
Expand All @@ -660,7 +662,7 @@ function determineAttributeDefaultValue(
return null
}

if (types.isSignedInteger(type)) {
if (await types.isSignedInteger(db, sessionId, type)) {
return '0x80' + '00'.repeat(typeSize - 1)
}

Expand All @@ -681,7 +683,7 @@ function determineAttributeDefaultValue(
* 2.) If client is included on at least one endpoint add client atts.
* 3.) If server is included on at least one endpoint add server atts.
*/
async function collectAttributes(endpointTypes, options) {
async function collectAttributes(db, sessionId, endpointTypes, options) {
let commandMfgCodes = [] // Array of { index, mfgCode } objects
let clusterMfgCodes = [] // Array of { index, mfgCode } objects
let attributeMfgCodes = [] // Array of { index, mfgCode } objects
Expand Down Expand Up @@ -710,7 +712,7 @@ async function collectAttributes(endpointTypes, options) {
? options.spaceForDefaultValue
: 2

endpointTypes.forEach((ept) => {
for (let ept of endpointTypes) {
let endpoint = {
clusterIndex: clusterIndex,
clusterCount: ept.clusters.length,
Expand All @@ -728,7 +730,7 @@ async function collectAttributes(endpointTypes, options) {

ept.clusters.sort(zclUtil.clusterComparator)

ept.clusters.forEach((c) => {
for (let c of ept.clusters) {
let cluster = {
endpointId: ept.endpointId,
clusterId: asMEI(c.manufacturerCode, c.code),
Expand All @@ -754,18 +756,20 @@ async function collectAttributes(endpointTypes, options) {
c.attributes.sort(zclUtil.attributeComparator)

// Go over all the attributes in the endpoint and add them to the list.
c.attributes.forEach((a) => {
for (let a of c.attributes) {
// typeSize is the size of a buffer needed to hold the attribute, if
// that's known.
let typeSize = a.typeSize
// defaultSize is the size of the attribute in the readonly defaults
// store.
let defaultSize = typeSize
let attributeDefaultValue = determineAttributeDefaultValue(
let attributeDefaultValue = await determineAttributeDefaultValue(
a.defaultValue,
a.type,
typeSize,
a.isNullable
a.isNullable,
db,
sessionId
)
// Various types store the length of the actual content in bytes.
// For those, we can size the default storage to be just big enough for
Expand Down Expand Up @@ -963,7 +967,7 @@ async function collectAttributes(endpointTypes, options) {
}
attributeMfgCodes.push(att)
}
})
}

// Go over the commands
c.commands.sort(zclUtil.commandComparator)
Expand Down Expand Up @@ -1051,10 +1055,10 @@ async function collectAttributes(endpointTypes, options) {
}
clusterMfgCodes.push(clt)
}
})
}
endpoint.attributeSize = endpointAttributeSize
endpointList.push(endpoint)
})
}

return {
endpointList: endpointList,
Expand Down Expand Up @@ -1269,7 +1273,7 @@ function endpoint_config(options) {
collectAttributeSizes(db, this.global.zclPackageIds, endpointTypes)
)
.then((endpointTypes) =>
collectAttributes(endpointTypes, collectAttributesOptions)
collectAttributes(db, sessionId, endpointTypes, collectAttributesOptions)
)
.then((collection) => {
Object.assign(newContext, collection)
Expand Down
32 changes: 15 additions & 17 deletions src-electron/util/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/

const queryZcl = require('../db/query-zcl.js')
const queryAtomic = require('../db/query-atomic.js')
const queryPackages = require('../db/query-package.js')
const dbEnum = require('../../src-shared/db-enum.js')
const bin = require('./bin')
const env = require('./env')
Expand Down Expand Up @@ -272,24 +274,20 @@ function isFloat(type) {
}

/**
* Returns true if a given ZCL type is a signed integer.
* @param {*} type
* @returns true if type is signed integer, false otherwise
* Checks if a given ZCL type is a signed integer.
*
* @param {object} db - The database connection object.
* @param {string} sessionId - The session ID.
* @param {string} type - The name of the ZCL type.
* @returns {Promise<boolean>} - A promise that resolves to true if the type is a signed integer, false otherwise.
*/
function isSignedInteger(type) {
switch (type) {
case 'int8s':
case 'int16s':
case 'int24s':
case 'int32s':
case 'int40s':
case 'int48s':
case 'int56s':
case 'int64s':
return true
default:
return false
}
async function isSignedInteger(db, sessionId, type) {
let sessionPackages = await queryPackages.getSessionPackages(db, sessionId)
return await queryAtomic.isTypeSignedByNameAndPackage(
db,
type,
sessionPackages
)
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src-electron/validation/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ async function validateSpecificAttribute(
//Interpreting float values
if (!checkAttributeBoundsFloat(attribute, endpointAttribute))
defaultAttributeIssues.push('Out of range')
} else if (types.isSignedInteger(attribute.type)) {
} else if (await types.isSignedInteger(db, zapSessionId, attribute.type)) {
if (!isValidSignedNumberString(endpointAttribute.defaultValue)) {
defaultAttributeIssues.push('Invalid Integer')
} else if (
Expand Down
3 changes: 3 additions & 0 deletions test/gen-matter-4.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ test(
expect(ept).toContain(
`{ 0x00000005, ZAP_TYPE(ENUM8), 1, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_EMPTY_DEFAULT() }, /* LastNetworkingStatus */`
)
expect(ept).toContain(
' { 0x00000000, ZAP_TYPE(TEMPERATURE), 2, ZAP_ATTRIBUTE_MASK(NULLABLE), ZAP_SIMPLE_DEFAULT(0x8000) },'
)
expect(ept).toContain(
'{ (uint16_t)0xFF, (uint16_t)0x64, (uint16_t)0xFFFF }, /* BallastFactorAdjustment */'
)
Expand Down
4 changes: 2 additions & 2 deletions test/resource/matter-all-clusters-file-format-2.zap
Original file line number Diff line number Diff line change
Expand Up @@ -8887,12 +8887,12 @@
"code": 0,
"mfgCode": null,
"side": "server",
"type": "int16s",
"type": "temperature",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 0,
"maxInterval": 65344,
Expand Down
2 changes: 1 addition & 1 deletion test/resource/matter-all-clusters.zap
Original file line number Diff line number Diff line change
Expand Up @@ -2291,7 +2291,7 @@
"0x0000 | | server | 1 | 0 => GetWeeklyScheduleResponse"
],
"attributes": [
"+ | 0x0000 | | server | RAM | | | | 1 | 0 | 65344 | 0 => LocalTemperature [int16s]",
"+ | 0x0000 | | server | RAM | | | | 1 | 0 | 65344 | 0 => LocalTemperature [temperature]",
"+ | 0x0003 | | server | RAM | | | 0x02BC | 1 | 0 | 65344 | 0 => AbsMinHeatSetpointLimit [int16s]",
"+ | 0x0004 | | server | RAM | | | 0x0BB8 | 1 | 0 | 65344 | 0 => AbsMaxHeatSetpointLimit [int16s]",
"+ | 0x0005 | | server | RAM | | | 0x0640 | 1 | 0 | 65344 | 0 => AbsMinCoolSetpointLimit [int16s]",
Expand Down
1 change: 1 addition & 0 deletions test/resource/old-matter/chip-types.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@ limitations under the License.
<type id="0xFD" description="IPv6 Prefix" name="ipv6pre" composite="true"/>
<type id="0xFE" description="Hardware Address" name="hwadr" composite="true"/>
<type id="0xFF" description="Unknown" name="unknown" size="0" />
<type id="0xD8" description="Temperature" name="temperature" size="2" analog="true" signed="true" />
</atomic>
</configurator>
1 change: 1 addition & 0 deletions zcl-builtin/matter/data-model/chip/chip-types.xml
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,6 @@ limitations under the License.
<type id="0xFD" description="IPv6 Prefix" name="ipv6pre" composite="true"/>
<type id="0xFE" description="Hardware Address" name="hwadr" composite="true"/>
<type id="0xFF" description="Unknown" name="unknown" size="0" />
<type id="0xD8" description="Temperature" name="temperature" size="2" analog="true" signed="true" />
</atomic>
</configurator>
2 changes: 1 addition & 1 deletion zcl-builtin/matter/data-model/chip/thermostat-cluster.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ limitations under the License.
<client tick="false" init="false">true</client>
<server tick="false" init="false">true</server>
<globalAttribute side="either" code="0xFFFD" value="5"/>
<attribute side="server" code="0x0000" define="LOCAL_TEMPERATURE" type="INT16S" min="0x954D" max="0x7FFF" writable="false" reportable="true" optional="false" isNullable="true">LocalTemperature</attribute>
<attribute side="server" code="0x0000" define="LOCAL_TEMPERATURE" type="TEMPERATURE" min="0x954D" max="0x7FFF" writable="false" reportable="true" optional="false" isNullable="true">LocalTemperature</attribute>
<attribute side="server" code="0x0001" define="OUTDOOR_TEMPERATURE" type="INT16S" min="0x954D" max="0x7FFF" writable="false" optional="true" isNullable="true">OutdoorTemperature</attribute>
<attribute side="server" code="0x0002" define="THERMOSTAT_OCCUPANCY" type="BITMAP8" min="0x00" max="0x01" writable="false" default="0x01" optional="true">Occupancy</attribute>
<!-- OCCUPANCY -->
Expand Down

0 comments on commit 1bf40e8

Please sign in to comment.