Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IM] Implement supported CommandList #14299

Merged
merged 19 commits into from
Feb 2, 2022
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions examples/lighting-app/lighting-common/lighting-app.matter
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,24 @@ client cluster OnOff = 6 {
attribute enum8 startUpOnOff = 16387;
readonly global attribute bitmap32 featureMap = 65532;
readonly global attribute int16u clusterRevision = 65533;

bzbarsky-apple marked this conversation as resolved.
Show resolved Hide resolved
request struct OffWithEffectRequest {
OnOffEffectIdentifier effectId = 0;
OnOffDelayedAllOffEffectVariant effectVariant = 1;
}

request struct OnWithTimedOffRequest {
OnOffControl onOffControl = 0;
int16u onTime = 1;
int16u offWaitTime = 2;
}

command Off(): DefaultSuccess = 0;
command OffWithEffect(OffWithEffectRequest): DefaultSuccess = 64;
command On(): DefaultSuccess = 1;
command OnWithRecallGlobalScene(): DefaultSuccess = 65;
command OnWithTimedOff(OnWithTimedOffRequest): DefaultSuccess = 66;
command Toggle(): DefaultSuccess = 2;
}

server cluster OnOff = 6 {
Expand All @@ -1037,24 +1055,6 @@ server cluster OnOff = 6 {
attribute enum8 startUpOnOff = 16387;
readonly global attribute bitmap32 featureMap = 65532;
readonly global attribute int16u clusterRevision = 65533;

request struct OffWithEffectRequest {
OnOffEffectIdentifier effectId = 0;
OnOffDelayedAllOffEffectVariant effectVariant = 1;
}

request struct OnWithTimedOffRequest {
OnOffControl onOffControl = 0;
int16u onTime = 1;
int16u offWaitTime = 2;
}

command Off(): DefaultSuccess = 0;
command OffWithEffect(OffWithEffectRequest): DefaultSuccess = 64;
command On(): DefaultSuccess = 1;
command OnWithRecallGlobalScene(): DefaultSuccess = 65;
command OnWithTimedOff(OnWithTimedOffRequest): DefaultSuccess = 66;
command Toggle(): DefaultSuccess = 2;
}

server cluster OnOffSwitchConfiguration = 7 {
Expand Down
12 changes: 12 additions & 0 deletions src/app/tests/suites/TestCluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3741,3 +3741,15 @@ tests:
# TODO: We don't have a way to represent cluster-specific status
# here yet.
error: FAILURE

- label: "read ClientGeneratedCommandList attribure"
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
command: "readAttribute"
attribute: "ClientGeneratedCommandList"
response:
value: [0, 1, 2, 4, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20]

- label: "read ServerGeneratedCommandList attribure"
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
command: "readAttribute"
attribute: "ServerGeneratedCommandList"
response:
value: [0, 1, 4, 5, 6, 9, 10]
12 changes: 12 additions & 0 deletions src/app/util/af-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ typedef struct
* if this cluster has no functions.
*/
const EmberAfGenericClusterFunction * functions;

/**
* A list of client generated commands. A client generated command
* is a client to server command. Terminated by 0xFFFF_FFFF.
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
*/
const chip::CommandId * clientGeneratedCommandList;

/**
* A list of server generated commands. A server generated command
* is a response to client command request. Terminated by 0xFFFF_FFFF.
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
*/
const chip::CommandId * serverGeneratedCommandList;
} EmberAfCluster;

/**
Expand Down
1 change: 1 addition & 0 deletions src/app/util/af.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include <app/util/debug-printing.h>
#include <app/util/ember-print.h>

#include <lib/core/DataModelTypes.h>
#include <lib/support/Iterators.h>
#include <lib/support/SafeInt.h>

Expand Down
1 change: 1 addition & 0 deletions src/app/util/attribute-storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ constexpr const EmberAfAttributeMinMaxValue minMaxDefaults[] = GENERATED_MIN_MAX
GENERATED_FUNCTION_ARRAYS
#endif

constexpr const chip::CommandId generatedCommands[] = GENERATED_COMMANDS;
constexpr const EmberAfAttributeMetadata generatedAttributes[] = GENERATED_ATTRIBUTES;
constexpr const EmberAfCluster generatedClusters[] = GENERATED_CLUSTERS;
constexpr const EmberAfEndpointType generatedEmberAfEndpointTypes[] = GENERATED_ENDPOINT_TYPES;
Expand Down
77 changes: 52 additions & 25 deletions src/app/util/ember-compatibility-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,39 +285,62 @@ class MandatoryGlobalAttributeReader : public AttributeAccessInterface
const EmberAfCluster * mCluster;
};

class AttributeListReader : public MandatoryGlobalAttributeReader
class GlobalListAttributeReader : public MandatoryGlobalAttributeReader
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
{
public:
AttributeListReader(const EmberAfCluster * aCluster) : MandatoryGlobalAttributeReader(aCluster) {}
GlobalListAttributeReader(const EmberAfCluster * aCluster) : MandatoryGlobalAttributeReader(aCluster) {}

CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
};

CHIP_ERROR AttributeListReader::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
CHIP_ERROR GlobalListAttributeReader::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
// The id of AttributeList is not in the attribute metadata.
using namespace Clusters::Globals::Attributes;
// The id of the attributes below is not in the attribute metadata.
// TODO: This does not play nicely with wildcard reads. Need to fix ZAP to
// put it in the metadata, or fix wildcard expansion to add it.
return aEncoder.EncodeList([this](const auto & encoder) {
constexpr AttributeId ourId = Clusters::Globals::Attributes::AttributeList::Id;
const size_t count = mCluster->attributeCount;
bool addedOurId = false;
for (size_t i = 0; i < count; ++i)
{
AttributeId id = mCluster->attributes[i].attributeId;
if (!addedOurId && id > ourId)
switch (aPath.mAttributeId)
{
case AttributeList::Id:
return aEncoder.EncodeList([this](const auto & encoder) {
constexpr AttributeId ourId = Clusters::Globals::Attributes::AttributeList::Id;
const size_t count = mCluster->attributeCount;
bool addedOurId = false;
for (size_t i = 0; i < count; ++i)
{
AttributeId id = mCluster->attributes[i].attributeId;
if (!addedOurId && id > ourId)
{
ReturnErrorOnFailure(encoder.Encode(ourId));
addedOurId = true;
}
ReturnErrorOnFailure(encoder.Encode(id));
}
if (!addedOurId)
{
ReturnErrorOnFailure(encoder.Encode(ourId));
addedOurId = true;
}
ReturnErrorOnFailure(encoder.Encode(id));
}
if (!addedOurId)
{
ReturnErrorOnFailure(encoder.Encode(ourId));
}
return CHIP_NO_ERROR;
});
case ClientGeneratedCommandList::Id:
return aEncoder.EncodeList([this](const auto & encoder) {
for (const CommandId * cmd = mCluster->clientGeneratedCommandList; cmd != nullptr && *cmd != kInvalidCommandId; cmd++)
{
ReturnErrorOnFailure(encoder.Encode(*cmd));
}
return CHIP_NO_ERROR;
});
case ServerGeneratedCommandList::Id:
return aEncoder.EncodeList([this](const auto & encoder) {
for (const CommandId * cmd = mCluster->serverGeneratedCommandList; cmd != nullptr && *cmd != kInvalidCommandId; cmd++)
{
ReturnErrorOnFailure(encoder.Encode(*cmd));
}
return CHIP_NO_ERROR;
});
default:
return CHIP_NO_ERROR;
});
}
}

// Helper function for trying to read an attribute value via an
Expand Down Expand Up @@ -366,12 +389,16 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b
EmberAfCluster * attributeCluster = nullptr;
EmberAfAttributeMetadata * attributeMetadata = nullptr;

if (aPath.mAttributeId == Clusters::Globals::Attributes::AttributeList::Id)
switch (aPath.mAttributeId)
{
case Clusters::Globals::Attributes::AttributeList::Id:
FALLTHROUGH;
case Clusters::Globals::Attributes::ClientGeneratedCommandList::Id:
FALLTHROUGH;
case Clusters::Globals::Attributes::ServerGeneratedCommandList::Id:
attributeCluster = emberAfFindCluster(aPath.mEndpointId, aPath.mClusterId, CLUSTER_MASK_SERVER);
}
else
{
break;
default:
attributeMetadata =
emberAfLocateAttributeMetadata(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId, CLUSTER_MASK_SERVER);
}
Expand Down Expand Up @@ -406,7 +433,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b
{
// Special handling for mandatory global attributes: these are always for attribute list, using a special
// reader (which can be lightweight constructed even from nullptr).
AttributeListReader reader(attributeCluster);
GlobalListAttributeReader reader(attributeCluster);
AttributeAccessInterface * attributeOverride =
(attributeCluster != nullptr) ? &reader : findAttributeAccessOverride(aPath.mEndpointId, aPath.mClusterId);
if (attributeOverride)
Expand Down
10 changes: 10 additions & 0 deletions src/app/zap-templates/templates/app/endpoint_config.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,22 @@
// This is an array of EmberAfCluster structures.
#define ZAP_ATTRIBUTE_INDEX(index) ((EmberAfAttributeMetadata *)(&generatedAttributes[index]))

#define ZAP_GENERATED_COMMANDS_INDEX(index) ((chip::CommandId *) (&generatedCommands[index]))

// Cluster function static arrays
#define GENERATED_FUNCTION_ARRAYS {{chip_endpoint_generated_functions}}

// clang-format off
#define GENERATED_COMMANDS {{chip_endpoint_generated_commands_list}}
// clang-format on

#define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_ ## mask
#define GENERATED_CLUSTER_COUNT {{endpoint_cluster_count}}


// clang-format off
#define GENERATED_CLUSTERS {{chip_endpoint_cluster_list}}
// clang-format on

#define ZAP_CLUSTER_INDEX(index) ((EmberAfCluster*)(&generatedClusters[index]))

Expand Down
103 changes: 82 additions & 21 deletions src/app/zap-templates/templates/app/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ zclHelper['isEvent'] = function(db, event_name, packageId) {
// This list of attributes is taken from section '11.2. Global Attributes' of the
// Data Model specification.
const kGlobalAttributes = [
0xfff8, // ServerGeneratedCommandList
0xfff9, // ClientGeneratedCommandList
0xfffb, // AttributeList
0xfffc, // ClusterRevision
0xfffd, // FeatureMap
Expand Down Expand Up @@ -178,14 +180,44 @@ function chip_endpoint_generated_functions()
return ret.concat('\n');
}

function chip_endpoint_generated_commands_list()
{
let ret = '{ \\\n';
this.clusterList.forEach((c) => {
let clientGeneratedCommands = [];
let serverGeneratedCommands = [];

c.commands.forEach((cmd) => {
if (cmd.mask.includes('incoming_server')) {
clientGeneratedCommands.push(`${cmd.commandId} /* ${cmd.name} */`);
}
if (cmd.mask.includes('incoming_client')) {
serverGeneratedCommands.push(`${cmd.commandId} /* ${cmd.name} */`);
}
});

ret = ret.concat(`/* ${c.comment} */\\\n`);
if (clientGeneratedCommands.length > 0) {
clientGeneratedCommands.push('chip::kInvalidCommandId /* end of list */')
ret = ret.concat(`/* incoming_server */ ${clientGeneratedCommands.join(' , ')}, \\\n`);
}
if (serverGeneratedCommands.length > 0) {
serverGeneratedCommands.push('chip::kInvalidCommandId /* end of list */')
ret = ret.concat(`/* incoming_client */ ${serverGeneratedCommands.join(' , ')}, \\\n`);
}
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
})
return ret.concat('}\n');
}

/**
* Return endpoint config GENERATED_CLUSTER MACRO
* To be used as a replacement of endpoint_cluster_list since this one
* includes the GENERATED_FUNCTIONS array
*/
function chip_endpoint_cluster_list()
{
let ret = '{ \\\n';
let ret = '{ \\\n';
let totalCommands = 0;
this.clusterList.forEach((c) => {
let mask = '';
let functionArray = c.functions;
Expand Down Expand Up @@ -223,8 +255,36 @@ function chip_endpoint_cluster_list()
} else {
mask = c.mask.map((m) => `ZAP_CLUSTER_MASK(${m.toUpperCase()})`).join(' | ')
}
ret = ret.concat(` { ${c.clusterId}, ZAP_ATTRIBUTE_INDEX(${c.attributeIndex}), ${c.attributeCount}, ${c.attributeSize}, ${
mask}, ${functionArray} }, /* ${c.comment} */ \\\n`)

let clientGeneratedCommands = c.commands.reduce(((acc, cmd) => (acc + (cmd.mask.includes('incoming_server') ? 1 : 0))), 0);
let serverGeneratedCommands = c.commands.reduce(((acc, cmd) => (acc + (cmd.mask.includes('incoming_client') ? 1 : 0))), 0);

let clientGeneratedCommandsListVal = "nullptr";
let serverGeneratedCommandsListVal = "nullptr";

if (clientGeneratedCommands > 0) {
clientGeneratedCommands++;
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
clientGeneratedCommandsListVal = `ZAP_GENERATED_COMMANDS_INDEX( ${totalCommands} )`;
}

if (serverGeneratedCommands > 0) {
serverGeneratedCommands++;
erjiaqing marked this conversation as resolved.
Show resolved Hide resolved
serverGeneratedCommandsListVal = `ZAP_GENERATED_COMMANDS_INDEX( ${totalCommands + clientGeneratedCommands} )`;
}

ret = ret.concat(` { \\
/* ${c.comment} */ \\
.clusterId = ${c.clusterId}, \\
.attributes = ZAP_ATTRIBUTE_INDEX(${c.attributeIndex}), \\
.attributeCount = ${c.attributeCount}, \\
.clusterSize = ${c.attributeSize}, \\
.mask = ${mask}, \\
.functions = ${functionArray}, \\
.clientGeneratedCommandList = ${clientGeneratedCommandsListVal} ,\\
.serverGeneratedCommandList = ${serverGeneratedCommandsListVal} ,\\
},\\\n`)

totalCommands = totalCommands + clientGeneratedCommands + serverGeneratedCommands;
})
return ret.concat('}\n');
}
Expand Down Expand Up @@ -726,21 +786,22 @@ async function zcl_events_fields_by_event_name(name, options)
//
// Module exports
//
exports.asPrintFormat = asPrintFormat;
exports.asReadType = asReadType;
exports.chip_endpoint_generated_functions = chip_endpoint_generated_functions
exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list
exports.asTypedLiteral = asTypedLiteral;
exports.asLowerCamelCase = asLowerCamelCase;
exports.asUpperCamelCase = asUpperCamelCase;
exports.hasProperty = hasProperty;
exports.hasSpecificAttributes = hasSpecificAttributes;
exports.asMEI = asMEI;
exports.zapTypeToEncodableClusterObjectType = zapTypeToEncodableClusterObjectType;
exports.zapTypeToDecodableClusterObjectType = zapTypeToDecodableClusterObjectType;
exports.zapTypeToPythonClusterObjectType = zapTypeToPythonClusterObjectType;
exports.getResponseCommandName = getResponseCommandName;
exports.isWeaklyTypedEnum = isWeaklyTypedEnum;
exports.getPythonFieldDefault = getPythonFieldDefault;
exports.incrementDepth = incrementDepth;
exports.zcl_events_fields_by_event_name = zcl_events_fields_by_event_name;
exports.asPrintFormat = asPrintFormat;
exports.asReadType = asReadType;
exports.chip_endpoint_generated_functions = chip_endpoint_generated_functions
exports.chip_endpoint_cluster_list = chip_endpoint_cluster_list
exports.chip_endpoint_generated_commands_list = chip_endpoint_generated_commands_list
exports.asTypedLiteral = asTypedLiteral;
exports.asLowerCamelCase = asLowerCamelCase;
exports.asUpperCamelCase = asUpperCamelCase;
exports.hasProperty = hasProperty;
exports.hasSpecificAttributes = hasSpecificAttributes;
exports.asMEI = asMEI;
exports.zapTypeToEncodableClusterObjectType = zapTypeToEncodableClusterObjectType;
exports.zapTypeToDecodableClusterObjectType = zapTypeToDecodableClusterObjectType;
exports.zapTypeToPythonClusterObjectType = zapTypeToPythonClusterObjectType;
exports.getResponseCommandName = getResponseCommandName;
exports.isWeaklyTypedEnum = isWeaklyTypedEnum;
exports.getPythonFieldDefault = getPythonFieldDefault;
exports.incrementDepth = incrementDepth;
exports.zcl_events_fields_by_event_name = zcl_events_fields_by_event_name;
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ limitations under the License.
<attribute side="client" code="0xFFFC" define="FEATURE_MAP_CLIENT" type="bitmap32" default="0" optional="true">FeatureMap</attribute>
<attribute side="server" code="0xFFFC" define="FEATURE_MAP_SERVER" type="bitmap32" default="0" optional="true">FeatureMap</attribute>
<attribute side="server" code="0xFFFB" define="ATTRIBUTE_LIST_SERVER" type="array" entryType="attrib_id">AttributeList</attribute>
<attribute side="server" code="0xFFF9" define="CLIENT_GENERATED_COMMAND_LIST" type="array" entryType="command_id">ClientGeneratedCommandList</attribute>
<attribute side="server" code="0xFFF8" define="SERVER_GENERATED_COMMAND_LIST" type="array" entryType="command_id">ServerGeneratedCommandList</attribute>

</global>
</configurator>
Loading