diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 43260d5ecc2f04..eefb773e8c4683 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -2607,6 +2607,8 @@ server cluster TestCluster = 1295 { readonly attribute LONG_OCTET_STRING listLongOctetString[] = 42; readonly attribute TestFabricScoped listFabricScoped[] = 43; attribute boolean timedWriteBoolean = 48; + attribute boolean generalErrorBoolean = 49; + attribute boolean clusterErrorBoolean = 50; attribute nullable boolean nullableBoolean = 32768; attribute nullable bitmap8 nullableBitmap8 = 32769; attribute nullable bitmap16 nullableBitmap16 = 32770; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index f6a66b319e1f8a..127bb9c5c7c210 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -1718,7 +1718,7 @@ "reportableChange": 0 }, { - "name": "CalendarType", + "name": "ActiveCalendarType", "code": 1, "mfgCode": null, "side": "server", @@ -16549,6 +16549,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "general_error_boolean", + "code": 49, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "cluster_error_boolean", + "code": 50, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "unsupported", "code": 255, @@ -17069,7 +17099,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -17084,7 +17114,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "0", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -20465,5 +20495,6 @@ "endpointVersion": 1, "deviceIdentifier": 256 } - ] -} + ], + "log": [] +} \ No newline at end of file diff --git a/examples/chip-tool/commands/common/CommandInvoker.h b/examples/chip-tool/commands/common/CommandInvoker.h index 1214361198a179..29088db1c09a32 100644 --- a/examples/chip-tool/commands/common/CommandInvoker.h +++ b/examples/chip-tool/commands/common/CommandInvoker.h @@ -106,7 +106,8 @@ class CommandInvoker final : public ResponseReceiverAddRequestData(commandPath, aRequestData)); - Optional session = exchangeManager->GetSessionManager()->CreateGroupSession(groupId); + Optional session = exchangeManager->GetSessionManager()->CreateGroupSession(groupId, fabric); if (!session.HasValue()) { return CHIP_ERROR_NO_MEMORY; @@ -231,7 +232,11 @@ CHIP_ERROR InvokeGroupCommand(DeviceProxy * aDevice, void * aContext, // invoker will be deleted by the onDone call before the return of InvokeGroupCommand // invoker should not be used after the InvokeGroupCommand call - ReturnErrorOnFailure(invoker->InvokeGroupCommand(aDevice->GetExchangeManager(), groupId, aRequestData)); + // + // We assume the aDevice already has a Case session which is way we can use he established Secure Session + ReturnErrorOnFailure(invoker->InvokeGroupCommand(aDevice->GetExchangeManager(), + aDevice->GetSecureSession().Value()->AsSecureSession()->GetFabricIndex(), + groupId, aRequestData)); // invoker is already deleted and is not to be used invoker.release(); diff --git a/examples/lighting-app/esp32/main/CMakeLists.txt b/examples/lighting-app/esp32/main/CMakeLists.txt index 0b2deeab79926a..fa6bc71be325cf 100644 --- a/examples/lighting-app/esp32/main/CMakeLists.txt +++ b/examples/lighting-app/esp32/main/CMakeLists.txt @@ -57,6 +57,7 @@ idf_component_register(PRIV_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/user-label-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/wifi-network-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" PRIV_REQUIRES chip QRCode bt led_strip app_update) set_property(TARGET ${COMPONENT_LIB} PROPERTY CXX_STANDARD 17) diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter index 3e08b82c466ec1..ff7ef39e3ccd87 100644 --- a/examples/lighting-app/lighting-common/lighting-app.matter +++ b/examples/lighting-app/lighting-common/lighting-app.matter @@ -542,6 +542,61 @@ server cluster GeneralDiagnostics = 51 { readonly global attribute int16u clusterRevision = 65533; } +server cluster Groups = 4 { + readonly attribute bitmap8 nameSupport = 0; + readonly global attribute int16u clusterRevision = 65533; + + request struct AddGroupRequest { + INT16U groupId = 0; + CHAR_STRING groupName = 1; + } + + request struct AddGroupIfIdentifyingRequest { + INT16U groupId = 0; + CHAR_STRING groupName = 1; + } + + request struct GetGroupMembershipRequest { + INT16U groupList[] = 0; + } + + request struct RemoveGroupRequest { + INT16U groupId = 0; + } + + request struct ViewGroupRequest { + INT16U groupId = 0; + } + + response struct AddGroupResponse { + ENUM8 status = 0; + INT16U groupId = 1; + } + + response struct GetGroupMembershipResponse { + INT8U capacity = 0; + INT16U groupList[] = 1; + } + + response struct RemoveGroupResponse { + ENUM8 status = 0; + INT16U groupId = 1; + } + + response struct ViewGroupResponse { + ENUM8 status = 0; + INT16U groupId = 1; + CHAR_STRING groupName = 2; + } + + command AddGroup(AddGroupRequest): AddGroupResponse = 0; + command AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5; + command GetGroupMembership(GetGroupMembershipRequest): GetGroupMembershipResponse = 2; + command RemoveAllGroups(): DefaultSuccess = 4; + command RemoveGroup(RemoveGroupRequest): RemoveGroupResponse = 3; + command ViewGroup(ViewGroupRequest): ViewGroupResponse = 1; +} + server cluster Identify = 3 { enum IdentifyEffectIdentifier : ENUM8 { kBlink = 0; @@ -1424,6 +1479,7 @@ endpoint 0 { server cluster FixedLabel; server cluster GeneralCommissioning; server cluster GeneralDiagnostics; + server cluster Groups; server cluster LocalizationConfiguration; server cluster NetworkCommissioning; binding cluster OtaSoftwareUpdateProvider; @@ -1440,6 +1496,7 @@ endpoint 0 { endpoint 1 { server cluster ColorControl; server cluster Descriptor; + server cluster Groups; server cluster Identify; server cluster LevelControl; server cluster OccupancySensing; diff --git a/examples/lighting-app/lighting-common/lighting-app.zap b/examples/lighting-app/lighting-common/lighting-app.zap index ca2047ae333efb..19f4059098f7ba 100644 --- a/examples/lighting-app/lighting-common/lighting-app.zap +++ b/examples/lighting-app/lighting-common/lighting-app.zap @@ -210,7 +210,7 @@ "mfgCode": null, "define": "GROUPS_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { "name": "AddGroupResponse", @@ -4653,7 +4653,7 @@ "mfgCode": null, "define": "GROUPS_CLUSTER", "side": "server", - "enabled": 0, + "enabled": 1, "commands": [ { "name": "AddGroupResponse", @@ -6734,6 +6734,26 @@ } ] }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "client", + "enabled": 0, + "commands": [], + "attributes": [] + }, + { + "name": "Groups", + "code": 4, + "mfgCode": null, + "define": "GROUPS_CLUSTER", + "side": "server", + "enabled": 0, + "commands": [], + "attributes": [] + }, { "name": "On/Off", "code": 6, diff --git a/examples/lighting-app/mbed/CMakeLists.txt b/examples/lighting-app/mbed/CMakeLists.txt index 38505dfc0c93b4..73df019875d8ac 100644 --- a/examples/lighting-app/mbed/CMakeLists.txt +++ b/examples/lighting-app/mbed/CMakeLists.txt @@ -101,6 +101,7 @@ target_sources(${APP_TARGET} PRIVATE ${CHIP_ROOT}/src/app/clusters/ota-requestor/ota-requestor-server.cpp ${CHIP_ROOT}/src/app/clusters/ota-requestor/BDXDownloader.cpp ${CHIP_ROOT}/src/app/clusters/ota-requestor/OTARequestor.cpp + ${CHIP_ROOT}/src/app/clusters/groups-server/groups-server.cpp ) target_link_libraries(${APP_TARGET} mbed-os-posix-socket mbed-os mbed-ble mbed-events mbed-netsocket mbed-storage mbed-storage-kv-global-api mbed-mbedtls mbed-emac chip) diff --git a/examples/lighting-app/telink/CMakeLists.txt b/examples/lighting-app/telink/CMakeLists.txt index b27eb35fff3680..7cefd3059f1bcd 100644 --- a/examples/lighting-app/telink/CMakeLists.txt +++ b/examples/lighting-app/telink/CMakeLists.txt @@ -100,4 +100,5 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/clusters/ota-requestor/ota-requestor-server.cpp ${CHIP_ROOT}/src/app/clusters/ota-requestor/BDXDownloader.cpp ${CHIP_ROOT}/src/app/clusters/ota-requestor/OTARequestor.cpp + ${CHIP_ROOT}/src/app/clusters/groups-server/groups-server.cpp ) diff --git a/src/app/CommandHandler.cpp b/src/app/CommandHandler.cpp index 4a2b77aeb983cd..b8e3b1970bd352 100644 --- a/src/app/CommandHandler.cpp +++ b/src/app/CommandHandler.cpp @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -127,7 +128,15 @@ CHIP_ERROR CommandHandler::ProcessInvokeRequest(System::PacketBufferHandle && pa VerifyOrReturnError(TLV::AnonymousTag() == invokeRequestsReader.GetTag(), CHIP_ERROR_INVALID_TLV_TAG); CommandDataIB::Parser commandData; ReturnErrorOnFailure(commandData.Init(invokeRequestsReader)); - ReturnErrorOnFailure(ProcessCommandDataIB(commandData)); + + if (mpExchangeCtx->IsGroupExchangeContext()) + { + ReturnErrorOnFailure(ProcessGroupCommandDataIB(commandData)); + } + else + { + ReturnErrorOnFailure(ProcessCommandDataIB(commandData)); + } } // if we have exhausted this container @@ -181,21 +190,24 @@ void CommandHandler::DecrementHoldOff() return; } - CHIP_ERROR err = CHIP_NO_ERROR; - if (!mpExchangeCtx->IsGroupExchangeContext()) + if (mpExchangeCtx->IsGroupExchangeContext()) { - err = SendCommandResponse(); + mpExchangeCtx->Close(); } - - if (err != CHIP_NO_ERROR) + else { - ChipLogError(DataManagement, "Failed to send command response: %" CHIP_ERROR_FORMAT, err.Format()); - // We marked the exchange as "WillSendMessage", need to shutdown the exchange manually to avoid leaking exchanges. - if (mpExchangeCtx != nullptr) + CHIP_ERROR err = SendCommandResponse(); + if (err != CHIP_NO_ERROR) { - mpExchangeCtx->Close(); + ChipLogError(DataManagement, "Failed to send command response: %" CHIP_ERROR_FORMAT, err.Format()); + // We marked the exchange as "WillSendMessage", need to shutdown the exchange manually to avoid leaking exchanges. + if (mpExchangeCtx != nullptr) + { + mpExchangeCtx->Close(); + } } } + Close(); } @@ -236,19 +248,7 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand err = commandPath.GetCommandId(&concretePath.mCommandId); SuccessOrExit(err); - if (mpExchangeCtx != nullptr && mpExchangeCtx->IsGroupExchangeContext()) - { - // TODO retrieve Endpoint ID with GroupDataProvider using GroupId and FabricId - // Issue 11075 - - // Using endpoint 1 for test purposes - concretePath.mEndpointId = 1; - err = CHIP_NO_ERROR; - } - else - { - err = commandPath.GetEndpointId(&concretePath.mEndpointId); - } + err = commandPath.GetEndpointId(&concretePath.mEndpointId); SuccessOrExit(err); VerifyOrExit(mpCallback->CommandExists(concretePath), err = CHIP_ERROR_INVALID_PROFILE_ID); @@ -312,6 +312,103 @@ CHIP_ERROR CommandHandler::ProcessCommandDataIB(CommandDataIB::Parser & aCommand return CHIP_NO_ERROR; } +CHIP_ERROR CommandHandler::ProcessGroupCommandDataIB(CommandDataIB::Parser & aCommandElement) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + CommandPathIB::Parser commandPath; + TLV::TLVReader commandDataReader; + ClusterId clusterId; + CommandId commandId; + GroupId groupId; + FabricIndex fabric; + + Credentials::GroupDataProvider::GroupEndpoint mapping; + Credentials::GroupDataProvider * groupDataProvider = Credentials::GetGroupDataProvider(); + Credentials::GroupDataProvider::EndpointIterator * iterator; + + err = aCommandElement.GetPath(&commandPath); + SuccessOrExit(err); + + err = commandPath.GetClusterId(&clusterId); + SuccessOrExit(err); + + err = commandPath.GetCommandId(&commandId); + SuccessOrExit(err); + + groupId = mpExchangeCtx->GetSessionHandle()->AsGroupSession()->GetGroupId(); + fabric = GetAccessingFabricIndex(); + + ChipLogDetail(DataManagement, + "Received group command for Group=%" PRIu16 " Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI, groupId, + ChipLogValueMEI(clusterId), ChipLogValueMEI(commandId)); + + err = aCommandElement.GetData(&commandDataReader); + if (CHIP_END_OF_TLV == err) + { + ChipLogDetail(DataManagement, + "Received command without data for Group=%" PRIu16 " Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI, + groupId, ChipLogValueMEI(clusterId), ChipLogValueMEI(commandId)); + err = CHIP_NO_ERROR; + } + SuccessOrExit(err); + + iterator = groupDataProvider->IterateEndpoints(fabric); + VerifyOrExit(iterator != nullptr, err = CHIP_ERROR_NO_MEMORY); + + while (iterator->Next(mapping)) + { + if (groupId != mapping.group_id) + { + continue; + } + + ChipLogDetail(DataManagement, + "Processing group command for Endpoint=%" PRIu16 " Cluster=" ChipLogFormatMEI " Command=" ChipLogFormatMEI, + mapping.endpoint_id, ChipLogValueMEI(clusterId), ChipLogValueMEI(commandId)); + + const ConcreteCommandPath concretePath(mapping.endpoint_id, clusterId, commandId); + + if (!mpCallback->CommandExists(concretePath)) + { + ChipLogError(DataManagement, "No Cluster " ChipLogFormatMEI " on Endpoint 0x%" PRIx16, ChipLogValueMEI(clusterId), + mapping.endpoint_id); + + continue; + } + + { + Access::SubjectDescriptor subjectDescriptor = mpExchangeCtx->GetSessionHandle()->GetSubjectDescriptor(); + Access::RequestPath requestPath{ .cluster = concretePath.mClusterId, .endpoint = concretePath.mEndpointId }; + Access::Privilege requestPrivilege = Access::Privilege::kOperate; // TODO: get actual request privilege + err = Access::GetAccessControl().Check(subjectDescriptor, requestPath, requestPrivilege); + err = CHIP_NO_ERROR; // TODO: remove override + if (err != CHIP_NO_ERROR) + { + continue; + } + } + + if ((err = MatterPreCommandReceivedCallback(concretePath)) == CHIP_NO_ERROR) + { + TLV::TLVReader dataReader(commandDataReader); + mpCallback->DispatchCommand(*this, concretePath, dataReader); + MatterPostCommandReceivedCallback(concretePath); + } + else + { + ChipLogError(DataManagement, + "Error when calling MatterPreCommandReceivedCallback for Endpoint=%" PRIu16 " Cluster=" ChipLogFormatMEI + " Command=" ChipLogFormatMEI " : %" CHIP_ERROR_FORMAT, + mapping.endpoint_id, ChipLogValueMEI(clusterId), ChipLogValueMEI(commandId), err.Format()); + continue; + } + } + iterator->Release(); + +exit: + return CHIP_NO_ERROR; +} + CHIP_ERROR CommandHandler::AddStatusInternal(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus, const Optional & aClusterStatus) diff --git a/src/app/CommandHandler.h b/src/app/CommandHandler.h index c864104a045f38..5fdd10cca1a668 100644 --- a/src/app/CommandHandler.h +++ b/src/app/CommandHandler.h @@ -248,7 +248,17 @@ class CommandHandler */ void Close(); + /** + * ProcessCommandDataIB is only called when a unicast invoke command request is received + * It requires the endpointId in its command path to be able to dispatch the command + */ CHIP_ERROR ProcessCommandDataIB(CommandDataIB::Parser & aCommandElement); + + /** + * ProcessGroupCommandDataIB is only called when a group invoke command request is received + * It doesn't need the endpointId in it's command path since it uses the GroupId in message metadata to find it + */ + CHIP_ERROR ProcessGroupCommandDataIB(CommandDataIB::Parser & aCommandElement); CHIP_ERROR SendCommandResponse(); CHIP_ERROR AddStatusInternal(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus, const Optional & aClusterStatus); diff --git a/src/app/MessageDef/AttributeReportIBs.cpp b/src/app/MessageDef/AttributeReportIBs.cpp index 5d626f7e5361ae..ef23d39c5895a7 100644 --- a/src/app/MessageDef/AttributeReportIBs.cpp +++ b/src/app/MessageDef/AttributeReportIBs.cpp @@ -96,5 +96,29 @@ AttributeReportIBs::Builder & AttributeReportIBs::Builder::EndOfAttributeReportI EndOfContainer(); return *this; } + +CHIP_ERROR AttributeReportIBs::Builder::EncodeAttributeStatus(const ConcreteReadAttributePath & aPath, const StatusIB & aStatus) +{ + AttributeReportIB::Builder & attributeReport = CreateAttributeReport(); + ReturnErrorOnFailure(GetError()); + AttributeStatusIB::Builder & attributeStatusIBBuilder = attributeReport.CreateAttributeStatus(); + ReturnErrorOnFailure(attributeReport.GetError()); + AttributePathIB::Builder & attributePathIBBuilder = attributeStatusIBBuilder.CreatePath(); + ReturnErrorOnFailure(attributeStatusIBBuilder.GetError()); + + attributePathIBBuilder.Endpoint(aPath.mEndpointId) + .Cluster(aPath.mClusterId) + .Attribute(aPath.mAttributeId) + .EndOfAttributePathIB(); + ReturnErrorOnFailure(attributePathIBBuilder.GetError()); + StatusIB::Builder & statusIBBuilder = attributeStatusIBBuilder.CreateErrorStatus(); + ReturnErrorOnFailure(attributeStatusIBBuilder.GetError()); + statusIBBuilder.EncodeStatusIB(aStatus); + ReturnErrorOnFailure(statusIBBuilder.GetError()); + + ReturnErrorOnFailure(attributeStatusIBBuilder.EndOfAttributeStatusIB().GetError()); + return attributeReport.EndOfAttributeReportIB().GetError(); +} + } // namespace app } // namespace chip diff --git a/src/app/MessageDef/AttributeReportIBs.h b/src/app/MessageDef/AttributeReportIBs.h index 3f241cedfb798f..16baa7b9ed3c5c 100644 --- a/src/app/MessageDef/AttributeReportIBs.h +++ b/src/app/MessageDef/AttributeReportIBs.h @@ -28,6 +28,8 @@ #include "AttributeReportIB.h" #include +#include +#include #include #include #include @@ -77,6 +79,11 @@ class Builder : public ArrayBuilder */ AttributeReportIBs::Builder & EndOfAttributeReportIBs(); + /** + * Encode an AttributeReportIB containing an AttributeStatus. + */ + CHIP_ERROR EncodeAttributeStatus(const ConcreteReadAttributePath & aPath, const StatusIB & aStatus); + private: AttributeReportIB::Builder mAttributeReport; }; diff --git a/src/app/WriteHandler.cpp b/src/app/WriteHandler.cpp index 209246c68e9f62..11e6bdf76456d0 100644 --- a/src/app/WriteHandler.cpp +++ b/src/app/WriteHandler.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include namespace chip { @@ -122,7 +123,8 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData AttributePathIB::Parser attributePath; ClusterInfo clusterInfo; TLV::TLVReader reader = aAttributeDataIBsReader; - err = element.Init(reader); + + err = element.Init(reader); SuccessOrExit(err); err = element.GetPath(&attributePath); @@ -136,19 +138,9 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData { err = CHIP_NO_ERROR; } - if (mpExchangeCtx->IsGroupExchangeContext()) - { - // TODO retrieve Endpoint ID with GroupDataProvider using GroupId and FabricId - // Issue 11075 - // Using endpoint 0 for test purposes - clusterInfo.mEndpointId = 0; - } - else - { - err = attributePath.GetEndpoint(&(clusterInfo.mEndpointId)); - SuccessOrExit(err); - } + err = attributePath.GetEndpoint(&(clusterInfo.mEndpointId)); + SuccessOrExit(err); err = attributePath.GetCluster(&(clusterInfo.mClusterId)); SuccessOrExit(err); @@ -173,7 +165,14 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData const ConcreteAttributePath concretePath = ConcreteAttributePath(clusterInfo.mEndpointId, clusterInfo.mClusterId, clusterInfo.mAttributeId); MatterPreAttributeWriteCallback(concretePath); + TLV::TLVWriter backup; + mWriteResponseBuilder.Checkpoint(backup); err = WriteSingleClusterData(subjectDescriptor, clusterInfo, dataReader, this); + if (err != CHIP_NO_ERROR) + { + mWriteResponseBuilder.Rollback(backup); + err = AddStatus(concretePath, StatusIB(err)); + } MatterPostAttributeWriteCallback(concretePath); } SuccessOrExit(err); @@ -188,6 +187,122 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataIBs(TLV::TLVReader & aAttributeData return err; } +CHIP_ERROR WriteHandler::ProcessGroupAttributeDataIBs(TLV::TLVReader & aAttributeDataIBsReader) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + ReturnErrorCodeIf(mpExchangeCtx == nullptr, CHIP_ERROR_INTERNAL); + const Access::SubjectDescriptor subjectDescriptor = mpExchangeCtx->GetSessionHandle()->AsGroupSession()->GetSubjectDescriptor(); + + while (CHIP_NO_ERROR == (err = aAttributeDataIBsReader.Next())) + { + chip::TLV::TLVReader dataReader; + AttributeDataIB::Parser element; + AttributePathIB::Parser attributePath; + ClusterInfo clusterInfo; + GroupId groupId; + FabricIndex fabric; + TLV::TLVReader reader = aAttributeDataIBsReader; + + Credentials::GroupDataProvider::GroupEndpoint mapping; + Credentials::GroupDataProvider * groupDataProvider = Credentials::GetGroupDataProvider(); + Credentials::GroupDataProvider::EndpointIterator * iterator; + + err = element.Init(reader); + SuccessOrExit(err); + + err = element.GetPath(&attributePath); + SuccessOrExit(err); + + // We are using the feature that the parser won't touch the value if the field does not exist, since all fields in the + // cluster info will be invalid / wildcard, it is safe to ignore CHIP_END_OF_TLV. + + err = attributePath.GetNode(&(clusterInfo.mNodeId)); + if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + } + + err = attributePath.GetCluster(&(clusterInfo.mClusterId)); + SuccessOrExit(err); + + err = attributePath.GetAttribute(&(clusterInfo.mAttributeId)); + SuccessOrExit(err); + + groupId = mpExchangeCtx->GetSessionHandle()->AsGroupSession()->GetGroupId(); + fabric = GetAccessingFabricIndex(); + + err = attributePath.GetListIndex(&(clusterInfo.mListIndex)); + if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + } + + err = element.GetData(&dataReader); + SuccessOrExit(err); + + ChipLogDetail(DataManagement, + "Received group attribute write for Group=%" PRIu16 " Cluster=" ChipLogFormatMEI + " attribute=" ChipLogFormatMEI, + groupId, ChipLogValueMEI(clusterInfo.mClusterId), ChipLogValueMEI(clusterInfo.mAttributeId)); + + iterator = groupDataProvider->IterateEndpoints(fabric); + VerifyOrExit(iterator != nullptr, err = CHIP_ERROR_NO_MEMORY); + + while (iterator->Next(mapping)) + { + if (groupId != mapping.group_id) + { + continue; + } + + clusterInfo.mEndpointId = mapping.endpoint_id; + + if (!clusterInfo.IsValidAttributePath() || clusterInfo.HasAttributeWildcard()) + { + ChipLogDetail(DataManagement, + "Invalid group attribute write for endpoint=%" PRIu16 " Cluster=" ChipLogFormatMEI + " attribute=" ChipLogFormatMEI, + mapping.endpoint_id, ChipLogValueMEI(clusterInfo.mClusterId), + ChipLogValueMEI(clusterInfo.mAttributeId)); + + continue; + } + + ChipLogDetail(DataManagement, + "Processing group attribute write for endpoint=%" PRIu16 " Cluster=" ChipLogFormatMEI + " attribute=" ChipLogFormatMEI, + mapping.endpoint_id, ChipLogValueMEI(clusterInfo.mClusterId), ChipLogValueMEI(clusterInfo.mAttributeId)); + + chip::TLV::TLVReader tmpDataReader(dataReader); + + const ConcreteAttributePath concretePath(clusterInfo.mEndpointId, clusterInfo.mClusterId, clusterInfo.mAttributeId); + + MatterPreAttributeWriteCallback(concretePath); + err = WriteSingleClusterData(subjectDescriptor, clusterInfo, tmpDataReader, this); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DataManagement, + "Error when calling WriteSingleClusterData for Endpoint=%" PRIu16 " Cluster=" ChipLogFormatMEI + " Attribute =" ChipLogFormatMEI " : %" CHIP_ERROR_FORMAT, + mapping.endpoint_id, ChipLogValueMEI(clusterInfo.mClusterId), + ChipLogValueMEI(clusterInfo.mAttributeId), err.Format()); + } + MatterPostAttributeWriteCallback(concretePath); + } + + iterator->Release(); + } + + if (CHIP_END_OF_TLV == err) + { + err = CHIP_NO_ERROR; + } +exit: + return err; +} + Status WriteHandler::ProcessWriteRequest(System::PacketBufferHandle && aPayload, bool aIsTimedWrite) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -243,7 +358,16 @@ Status WriteHandler::ProcessWriteRequest(System::PacketBufferHandle && aPayload, } AttributeDataIBsParser.GetReader(&AttributeDataIBsReader); - err = ProcessAttributeDataIBs(AttributeDataIBsReader); + + if (mpExchangeCtx->IsGroupExchangeContext()) + { + err = ProcessGroupAttributeDataIBs(AttributeDataIBsReader); + } + else + { + err = ProcessAttributeDataIBs(AttributeDataIBsReader); + } + if (err == CHIP_NO_ERROR) { status = Status::Success; @@ -253,8 +377,12 @@ Status WriteHandler::ProcessWriteRequest(System::PacketBufferHandle && aPayload, return status; } -CHIP_ERROR WriteHandler::AddStatus(const AttributePathParams & aAttributePathParams, - const Protocols::InteractionModel::Status aStatus) +CHIP_ERROR WriteHandler::AddStatus(const ConcreteAttributePath & aPath, const Protocols::InteractionModel::Status aStatus) +{ + return AddStatus(aPath, StatusIB(aStatus)); +} + +CHIP_ERROR WriteHandler::AddStatus(const ConcreteAttributePath & aPath, const StatusIB & aStatus) { AttributeStatusIBs::Builder & writeResponses = mWriteResponseBuilder.GetWriteResponses(); AttributeStatusIB::Builder & attributeStatusIB = writeResponses.CreateAttributeStatus(); @@ -262,13 +390,11 @@ CHIP_ERROR WriteHandler::AddStatus(const AttributePathParams & aAttributePathPar AttributePathIB::Builder & path = attributeStatusIB.CreatePath(); ReturnErrorOnFailure(attributeStatusIB.GetError()); - ReturnErrorOnFailure(path.Encode(aAttributePathParams)); + ReturnErrorOnFailure(path.Encode(AttributePathParams(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId))); - StatusIB statusIB; - statusIB.mStatus = aStatus; StatusIB::Builder & statusIBBuilder = attributeStatusIB.CreateErrorStatus(); ReturnErrorOnFailure(attributeStatusIB.GetError()); - statusIBBuilder.EncodeStatusIB(statusIB); + statusIBBuilder.EncodeStatusIB(aStatus); ReturnErrorOnFailure(statusIBBuilder.GetError()); attributeStatusIB.EndOfAttributeStatusIB(); ReturnErrorOnFailure(attributeStatusIB.GetError()); diff --git a/src/app/WriteHandler.h b/src/app/WriteHandler.h index b6c838641f8b87..f4aed5736260f5 100644 --- a/src/app/WriteHandler.h +++ b/src/app/WriteHandler.h @@ -74,8 +74,10 @@ class WriteHandler virtual ~WriteHandler() = default; CHIP_ERROR ProcessAttributeDataIBs(TLV::TLVReader & aAttributeDataIBsReader); + CHIP_ERROR ProcessGroupAttributeDataIBs(TLV::TLVReader & aAttributeDataIBsReader); - CHIP_ERROR AddStatus(const AttributePathParams & aAttributePathParams, const Protocols::InteractionModel::Status aStatus); + CHIP_ERROR AddStatus(const ConcreteAttributePath & aPath, const Protocols::InteractionModel::Status aStatus); + CHIP_ERROR AddStatus(const ConcreteAttributePath & aPath, const StatusIB & aStatus); CHIP_ERROR AddClusterSpecificSuccess(const AttributePathParams & aAttributePathParams, uint8_t aClusterStatus) { diff --git a/src/app/clusters/test-cluster-server/test-cluster-server.cpp b/src/app/clusters/test-cluster-server/test-cluster-server.cpp index 5281598cf27309..4f39351ede060f 100644 --- a/src/app/clusters/test-cluster-server/test-cluster-server.cpp +++ b/src/app/clusters/test-cluster-server/test-cluster-server.cpp @@ -134,6 +134,12 @@ CHIP_ERROR TestAttrAccess::Read(const ConcreteReadAttributePath & aPath, Attribu case NullableStruct::Id: { return ReadNullableStruct(aEncoder); } + case GeneralErrorBoolean::Id: { + return StatusIB(Protocols::InteractionModel::Status::InvalidDataType).ToChipError(); + } + case ClusterErrorBoolean::Id: { + return StatusIB(Protocols::InteractionModel::Status::Failure, 17).ToChipError(); + } default: { break; } @@ -164,6 +170,12 @@ CHIP_ERROR TestAttrAccess::Write(const ConcreteDataAttributePath & aPath, Attrib case NullableStruct::Id: { return WriteNullableStruct(aDecoder); } + case GeneralErrorBoolean::Id: { + return StatusIB(Protocols::InteractionModel::Status::InvalidDataType).ToChipError(); + } + case ClusterErrorBoolean::Id: { + return StatusIB(Protocols::InteractionModel::Status::Failure, 17).ToChipError(); + } default: { break; } diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index c28ef733332ea2..063fb8d27f8904 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -126,7 +126,7 @@ CHIP_ERROR Engine::BuildSingleReportDataAttributeReportIBs(ReportDataMessage::Bu "Error retrieving data from clusterId: " ChipLogFormatMEI ", err = %" CHIP_ERROR_FORMAT, ChipLogValueMEI(pathForRetrieval.mClusterId), err.Format()); - if (encodeState.AllowPartialData()) + if (encodeState.AllowPartialData() && ((err == CHIP_ERROR_BUFFER_TOO_SMALL) || (err == CHIP_ERROR_NO_MEMORY))) { // Encoding is aborted but partial data is allowed, then we don't rollback and save the state for next chunk. apReadHandler->SetAttributeEncodeState(encodeState); @@ -137,6 +137,14 @@ CHIP_ERROR Engine::BuildSingleReportDataAttributeReportIBs(ReportDataMessage::Bu // attributeReportIB to avoid any partial data. attributeReportIBs.Rollback(attributeBackup); apReadHandler->SetAttributeEncodeState(AttributeValueEncoder::AttributeEncodeState()); + + // Try to encode our error as a status response. + err = attributeReportIBs.EncodeAttributeStatus(pathForRetrieval, StatusIB(err)); + if (err != CHIP_NO_ERROR) + { + // OK, just roll back again and give up. + attributeReportIBs.Rollback(attributeBackup); + } } } SuccessOrExit(err); diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 5721659da0a118..28e49475510439 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -149,21 +149,15 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint #endif ); + err = mListener.Init(&mTransports); + SuccessOrExit(err); + mGroupsProvider.SetListener(&mListener); + #if CONFIG_NETWORK_LAYER_BLE mBleLayer = DeviceLayer::ConnectivityMgr().GetBleLayer(); #endif SuccessOrExit(err); -// Enable Group Listening -// TODO : Fix this once GroupDataProvider is implemented #Issue 11075 -// for (iterate through all GroupDataProvider multicast Address) -// { -#ifdef CHIP_ENABLE_GROUP_MESSAGING_TESTS - err = mTransports.MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(0, 1234), true); - SuccessOrExit(err); -#endif - //} - err = mSessions.Init(&DeviceLayer::SystemLayer(), &mTransports, &mMessageCounterManager); SuccessOrExit(err); @@ -238,6 +232,40 @@ CHIP_ERROR Server::Init(AppDelegate * delegate, uint16_t secureServicePort, uint err = mCASESessionManager.Init(); + // This code is necessary to restart listening to existing groups after a reboot + // Each manufacturer needs to validate that they can rejoin groups by placing this code at the appropriate location for them + // + // This is disabled for thread device because the same code is already present for thread devices in + // src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread_LwIP.cpp + // https://github.com/project-chip/connectedhomeip/issues/14254 +#if !CHIP_DEVICE_CONFIG_ENABLE_THREAD + { + ChipLogProgress(AppServer, "Adding Multicast groups"); + ConstFabricIterator fabricIterator = mFabrics.cbegin(); + while (!fabricIterator.IsAtEnd()) + { + const FabricInfo & fabric = *fabricIterator; + Credentials::GroupDataProvider::GroupInfo groupInfo; + + Credentials::GroupDataProvider::GroupInfoIterator * iterator = + mGroupsProvider.IterateGroupInfo(fabric.GetFabricIndex()); + while (iterator->Next(groupInfo)) + { + err = mTransports.MulticastGroupJoinLeave( + Transport::PeerAddress::Multicast(fabric.GetFabricIndex(), groupInfo.group_id), true); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Error when trying to join Group %" PRIu16 " of fabric index %" PRIu8, + groupInfo.group_id, fabric.GetFabricIndex()); + break; + } + } + + fabricIterator++; + iterator->Release(); + } + } +#endif // !CHIP_DEVICE_CONFIG_ENABLE_THREAD exit: if (err != CHIP_NO_ERROR) { diff --git a/src/app/server/Server.h b/src/app/server/Server.h index a10e5bcf4695df..46258222705953 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -135,6 +135,37 @@ class Server CHIP_ERROR SyncDelete(FabricIndex fabricIndex, const char * key) override { return SyncDeleteKeyValue(key); }; }; + class GroupDataProviderListener final : public Credentials::GroupDataProvider::GroupListener + { + public: + GroupDataProviderListener() {} + + CHIP_ERROR Init(ServerTransportMgr * transports) + { + VerifyOrReturnError(transports != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + mTransports = transports; + return CHIP_NO_ERROR; + }; + + void OnGroupAdded(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & new_group) override + { + if (mTransports->MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(fabric_index, new_group.group_id), true) != + CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Unable to listen to group"); + } + }; + + void OnGroupRemoved(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & old_group) override + { + mTransports->MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(fabric_index, old_group.group_id), false); + }; + + private: + ServerTransportMgr * mTransports; + }; + #if CONFIG_NETWORK_LAYER_BLE Ble::BleLayer * mBleLayer = nullptr; #endif @@ -168,6 +199,7 @@ class Server #endif Credentials::GroupDataProviderImpl mGroupsProvider; app::DefaultAttributePersistenceProvider mAttributePersister; + GroupDataProviderListener mListener; // TODO @ceille: Maybe use OperationalServicePort and CommissionableServicePort uint16_t mSecuredServicePort; diff --git a/src/app/tests/TestWriteInteraction.cpp b/src/app/tests/TestWriteInteraction.cpp index 0f87a42cddcb09..fc0faf8853a1b7 100644 --- a/src/app/tests/TestWriteInteraction.cpp +++ b/src/app/tests/TestWriteInteraction.cpp @@ -19,11 +19,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -107,12 +109,9 @@ void TestWriteInteraction::AddAttributeDataIB(nlTestSuite * apSuite, void * apCo void TestWriteInteraction::AddAttributeStatus(nlTestSuite * apSuite, void * apContext, WriteHandler & aWriteHandler) { CHIP_ERROR err = CHIP_NO_ERROR; - AttributePathParams attributePathParams; - attributePathParams.mEndpointId = 2; - attributePathParams.mClusterId = 3; - attributePathParams.mAttributeId = 4; + ConcreteAttributePath attributePath(2, 3, 4); - err = aWriteHandler.AddStatus(attributePathParams, Protocols::InteractionModel::Status::Success); + err = aWriteHandler.AddStatus(attributePath, Protocols::InteractionModel::Status::Success); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); } @@ -310,7 +309,7 @@ CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDesc writer.CopyElement(TLV::AnonymousTag(), aReader); attributeDataTLVLen = writer.GetLengthWritten(); return aWriteHandler->AddStatus( - AttributePathParams(aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mAttributeId), + ConcreteAttributePath(aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mAttributeId), Protocols::InteractionModel::Status::Success); } @@ -419,6 +418,12 @@ void TestWriteInteraction::TestWriteRoundtrip(nlTestSuite * apSuite, void * apCo namespace { +constexpr uint16_t kMaxGroupsPerFabric = 5; +constexpr uint16_t kMaxGroupKeysPerFabric = 8; + +static chip::TestPersistentStorageDelegate sDelegate; +static chip::Credentials::GroupDataProviderImpl sProvider(sDelegate, kMaxGroupsPerFabric, kMaxGroupKeysPerFabric); + /** * Test Suite. It lists all the test functions. */ @@ -436,12 +441,47 @@ const nlTest sTests[] = // clang-format on // clang-format off + +/** + * Set up the test suite. + */ +int Test_Setup(void * inContext) +{ + SetGroupDataProvider(&sProvider); + VerifyOrReturnError(CHIP_NO_ERROR == chip::Platform::MemoryInit(), FAILURE); + VerifyOrReturnError(CHIP_NO_ERROR == sProvider.Init(), FAILURE); + + + VerifyOrReturnError(TestContext::Initialize(inContext) == SUCCESS, FAILURE); + + return SUCCESS; +} + +/** + * Tear down the test suite. + */ +int Test_Teardown(void * inContext) +{ + chip::Platform::MemoryShutdown(); + chip::Credentials::GroupDataProvider * provider = chip::Credentials::GetGroupDataProvider(); + if (nullptr != provider) + { + provider->Finish(); + } + + + VerifyOrReturnError(TestContext::Finalize(inContext) == SUCCESS, FAILURE); + + + return SUCCESS; +} + nlTestSuite sSuite = { "TestWriteInteraction", &sTests[0], - TestContext::Initialize, - TestContext::Finalize + &Test_Setup, + &Test_Teardown }; // clang-format on diff --git a/src/app/tests/integration/chip_im_responder.cpp b/src/app/tests/integration/chip_im_responder.cpp index e615b5a2d3bbfa..aeacfba944d004 100644 --- a/src/app/tests/integration/chip_im_responder.cpp +++ b/src/app/tests/integration/chip_im_responder.cpp @@ -118,11 +118,8 @@ CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDesc TLV::TLVReader & aReader, WriteHandler * apWriteHandler) { CHIP_ERROR err = CHIP_NO_ERROR; - AttributePathParams attributePathParams; - attributePathParams.mEndpointId = 2; - attributePathParams.mClusterId = 3; - attributePathParams.mAttributeId = 4; - err = apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::Success); + ConcreteAttributePath attributePath(2, 3, 4); + err = apWriteHandler->AddStatus(attributePath, Protocols::InteractionModel::Status::Success); return err; } } // namespace app diff --git a/src/app/tests/suites/TestCluster.yaml b/src/app/tests/suites/TestCluster.yaml index 290a243d75f630..4fbb5cfbedd186 100644 --- a/src/app/tests/suites/TestCluster.yaml +++ b/src/app/tests/suites/TestCluster.yaml @@ -3709,3 +3709,35 @@ tests: attribute: "nullable_range_restricted_int16s" response: value: null + + - label: "Write attribute that returns general status on write" + command: "writeAttribute" + attribute: "general_error_boolean" + arguments: + value: false + response: + error: INVALID_DATA_TYPE + + - label: "Write attribute that returns cluster-specific status on write" + command: "writeAttribute" + attribute: "cluster_error_boolean" + arguments: + value: false + response: + # TODO: We don't have a way to represent cluster-specific status + # here yet. + error: FAILURE + + - label: "Read attribute that returns general status on read" + command: "readAttribute" + attribute: "general_error_boolean" + response: + error: INVALID_DATA_TYPE + + - label: "read attribute that returns cluster-specific status on read" + command: "readAttribute" + attribute: "cluster_error_boolean" + response: + # TODO: We don't have a way to represent cluster-specific status + # here yet. + error: FAILURE diff --git a/src/app/tests/suites/TestGroupMessaging.yaml b/src/app/tests/suites/TestGroupMessaging.yaml index cb151176a75796..9bd05e97e41c03 100644 --- a/src/app/tests/suites/TestGroupMessaging.yaml +++ b/src/app/tests/suites/TestGroupMessaging.yaml @@ -29,14 +29,45 @@ tests: cluster: "DelayCommands" command: "WaitForCommissionee" - #TODO : Add Group membership command when implemented Issue #11077 - # - label: "Add device to Group" - # command: "TODO" + - label: "Add Group 1 - endpoint 1" + cluster: "Groups" + command: "AddGroup" + endpoint: 1 + arguments: + values: + - name: "groupId" + value: 0x1234 + - name: "groupName" + value: "Group #1" + response: + values: + - name: "status" + value: 0 + - name: "groupId" + value: 0x1234 + + - label: "Add Group 2 - endpoint 0" + cluster: "Groups" + command: "AddGroup" + endpoint: 0 + arguments: + values: + - name: "groupId" + value: 0x0001 + - name: "groupName" + value: "Group #2" + response: + values: + - name: "status" + value: 0 + - name: "groupId" + value: 0x0001 + # Test Pair 1 : Sends a Group Write Attribute - label: "Group Write Attribute" command: "writeAttribute" attribute: "location" - groupId: "1234" + groupId: "1" arguments: value: "us" @@ -51,7 +82,7 @@ tests: - label: "Restore initial location value" command: "writeAttribute" attribute: "location" - groupId: "1234" + groupId: "1" arguments: value: "" @@ -66,10 +97,11 @@ tests: - label: "Turn On the light to see attribute change" cluster: "On/Off" command: "On" - groupId: "1234" + groupId: "4660" - # Test Pair 3 : Validates previous group command with a unicast to read - - label: "Check on/off attribute value is true after on command" + # Test Pair 3 : Validates previous group command with a unicast to read + - label: + "Check on/off attribute value is true after on command for endpoint 1" cluster: "On/Off" command: "readAttribute" attribute: "OnOff" diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 45494a42aed398..139503672141c9 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -158,6 +158,10 @@ void SetupEmberAfCommandSender(CommandSender * command, const ConcreteCommandPat { imCompatibilityEmberAfCluster.type = EMBER_INCOMING_MULTICAST; } + else + { + imCompatibilityEmberAfCluster.type = EMBER_INCOMING_UNICAST; + } imCompatibilityEmberAfCluster.commandId = commandPath.mCommandId; imCompatibilityEmberAfCluster.apsFrame = &imCompatibilityEmberApsFrame; @@ -181,6 +185,10 @@ void SetupEmberAfCommandHandler(CommandHandler * command, const ConcreteCommandP { imCompatibilityEmberAfCluster.type = EMBER_INCOMING_MULTICAST; } + else + { + imCompatibilityEmberAfCluster.type = EMBER_INCOMING_UNICAST; + } imCompatibilityEmberAfCluster.commandId = commandPath.mCommandId; imCompatibilityEmberAfCluster.apsFrame = &imCompatibilityEmberApsFrame; @@ -254,30 +262,14 @@ CHIP_ERROR SendSuccessStatus(AttributeReportIB::Builder & aAttributeReport, Attr return aAttributeReport.EndOfAttributeReportIB().GetError(); } -CHIP_ERROR SendFailureStatus(const ConcreteAttributePath & aPath, AttributeReportIB::Builder & aAttributeReport, +CHIP_ERROR SendFailureStatus(const ConcreteAttributePath & aPath, AttributeReportIBs::Builder & aAttributeReports, Protocols::InteractionModel::Status aStatus, TLV::TLVWriter * aReportCheckpoint) { if (aReportCheckpoint != nullptr) { - aAttributeReport.Rollback(*aReportCheckpoint); + aAttributeReports.Rollback(*aReportCheckpoint); } - AttributeStatusIB::Builder & attributeStatusIBBuilder = aAttributeReport.CreateAttributeStatus(); - ReturnErrorOnFailure(aAttributeReport.GetError()); - AttributePathIB::Builder & attributePathIBBuilder = attributeStatusIBBuilder.CreatePath(); - ReturnErrorOnFailure(attributeStatusIBBuilder.GetError()); - - attributePathIBBuilder.Endpoint(aPath.mEndpointId) - .Cluster(aPath.mClusterId) - .Attribute(aPath.mAttributeId) - .EndOfAttributePathIB(); - ReturnErrorOnFailure(attributePathIBBuilder.GetError()); - StatusIB::Builder & statusIBBuilder = attributeStatusIBBuilder.CreateErrorStatus(); - ReturnErrorOnFailure(attributeStatusIBBuilder.GetError()); - statusIBBuilder.EncodeStatusIB(StatusIB(aStatus)); - ReturnErrorOnFailure(statusIBBuilder.GetError()); - - ReturnErrorOnFailure(attributeStatusIBBuilder.EndOfAttributeStatusIB().GetError()); - return aAttributeReport.EndOfAttributeReportIB().GetError(); + return aAttributeReports.EncodeAttributeStatus(aPath, StatusIB(aStatus)); } // This reader should never actually be registered; we do manual dispatch to it @@ -336,8 +328,6 @@ CHIP_ERROR ReadViaAccessInterface(FabricIndex aAccessingFabricIndex, bool aIsFab AttributeValueEncoder::AttributeEncodeState * aEncoderState, AttributeAccessInterface * aAccessInterface, bool * aTriedEncode) { - // TODO: We should probably clone the writer and convert failures here - // into status responses, unless our caller already does that. AttributeValueEncoder::AttributeEncodeState state = (aEncoderState == nullptr ? AttributeValueEncoder::AttributeEncodeState() : *aEncoderState); AttributeValueEncoder valueEncoder(aAttributeReports, aAccessingFabricIndex, aPath, kTemporaryDataVersion, aIsFabricFiltered, @@ -388,9 +378,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b if (attributeCluster == nullptr && attributeMetadata == nullptr) { - AttributeReportIB::Builder & attributeReport = aAttributeReports.CreateAttributeReport(); - ReturnErrorOnFailure(aAttributeReports.GetError()); - return SendFailureStatus(aPath, attributeReport, Protocols::InteractionModel::Status::UnsupportedAttribute, nullptr); + return SendFailureStatus(aPath, aAttributeReports, Protocols::InteractionModel::Status::UnsupportedAttribute, nullptr); } // Check access control. A failed check will disallow the operation, and may or may not generate an attribute report @@ -410,9 +398,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b } else { - AttributeReportIB::Builder & attributeReport = aAttributeReports.CreateAttributeReport(); - ReturnErrorOnFailure(aAttributeReports.GetError()); - return SendFailureStatus(aPath, attributeReport, Protocols::InteractionModel::Status::UnsupportedAccess, nullptr); + return SendFailureStatus(aPath, aAttributeReports, Protocols::InteractionModel::Status::UnsupportedAccess, nullptr); } } } @@ -434,12 +420,12 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b // Read attribute using Ember, if it doesn't have an override. + TLV::TLVWriter backup; + aAttributeReports.Checkpoint(backup); + AttributeReportIB::Builder & attributeReport = aAttributeReports.CreateAttributeReport(); ReturnErrorOnFailure(aAttributeReports.GetError()); - TLV::TLVWriter backup; - attributeReport.Checkpoint(backup); - AttributeDataIB::Builder & attributeDataIBBuilder = attributeReport.CreateAttributeData(); ReturnErrorOnFailure(attributeDataIBBuilder.GetError()); @@ -670,7 +656,7 @@ CHIP_ERROR ReadSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, b return SendSuccessStatus(attributeReport, attributeDataIBBuilder); } - return SendFailureStatus(aPath, attributeReport, imStatus, &backup); + return SendFailureStatus(aPath, aAttributeReports, imStatus, &backup); } namespace { @@ -820,16 +806,14 @@ CHIP_ERROR WriteSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, const EmberAfAttributeMetadata * attributeMetadata = emberAfLocateAttributeMetadata(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId, CLUSTER_MASK_SERVER); - AttributePathParams attributePathParams(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId); - if (attributeMetadata == nullptr) { - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::UnsupportedAttribute); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::UnsupportedAttribute); } if (attributeMetadata->IsReadOnly()) { - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::UnsupportedWrite); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::UnsupportedWrite); } { @@ -841,13 +825,13 @@ CHIP_ERROR WriteSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, { ReturnErrorCodeIf(err != CHIP_ERROR_ACCESS_DENIED, err); // TODO: when wildcard/group writes are supported, handle them to discard rather than fail with status - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::UnsupportedAccess); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::UnsupportedAccess); } } if (attributeMetadata->MustUseTimedWrite() && !apWriteHandler->IsTimedWrite()) { - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::NeedsTimedInteraction); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::NeedsTimedInteraction); } if (auto * attrOverride = findAttributeAccessOverride(aClusterInfo.mEndpointId, aClusterInfo.mClusterId)) @@ -858,7 +842,7 @@ CHIP_ERROR WriteSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, if (valueDecoder.TriedDecode()) { MatterReportingAttributeChangeCallback(aPath); - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::Success); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::Success); } } @@ -867,19 +851,19 @@ CHIP_ERROR WriteSingleClusterData(const SubjectDescriptor & aSubjectDescriptor, if ((preparationError = prepareWriteData(attributeMetadata, aReader, dataLen)) != CHIP_NO_ERROR) { ChipLogDetail(Zcl, "Failed to prepare data to write: %s", ErrorStr(preparationError)); - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::InvalidValue); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::InvalidValue); } if (dataLen > attributeMetadata->size) { ChipLogDetail(Zcl, "Data to write exceedes the attribute size claimed."); - return apWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::InvalidValue); + return apWriteHandler->AddStatus(aPath, Protocols::InteractionModel::Status::InvalidValue); } auto status = ToInteractionModelStatus(emberAfWriteAttributeExternal(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId, CLUSTER_MASK_SERVER, attributeData, attributeMetadata->attributeType)); - return apWriteHandler->AddStatus(attributePathParams, status); + return apWriteHandler->AddStatus(aPath, status); } } // namespace app diff --git a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml index fb98cd3e02ad60..7730ffab49c181 100644 --- a/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/test-cluster.xml @@ -153,6 +153,12 @@ limitations under the License. list_fabric_scoped timed_write_boolean + + general_error_boolean + cluster_error_boolean nullable_boolean nullable_bitmap8 diff --git a/src/controller/CHIPCluster.cpp b/src/controller/CHIPCluster.cpp index 34a3f681261b39..ef94a7c2c823b2 100644 --- a/src/controller/CHIPCluster.cpp +++ b/src/controller/CHIPCluster.cpp @@ -52,7 +52,8 @@ CHIP_ERROR ClusterBase::AssociateWithGroup(DeviceProxy * device, GroupId groupId if (mDevice->GetSecureSession().HasValue()) { // Local copy to preserve original SessionHandle for future Unicast communication. - Optional session = mDevice->GetExchangeManager()->GetSessionManager()->CreateGroupSession(groupId); + Optional session = mDevice->GetExchangeManager()->GetSessionManager()->CreateGroupSession( + groupId, mDevice->GetSecureSession().Value()->AsSecureSession()->GetFabricIndex()); // Sanity check if (!session.HasValue() || !session.Value()->IsGroupSession()) { diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 4dc73c46e6342c..fcb80bb3e6e29a 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -2847,6 +2847,8 @@ client cluster TestCluster = 1295 { attribute int16s rangeRestrictedInt16s = 41; readonly attribute LONG_OCTET_STRING listLongOctetString[] = 42; attribute boolean timedWriteBoolean = 48; + attribute boolean generalErrorBoolean = 49; + attribute boolean clusterErrorBoolean = 50; attribute boolean unsupported = 255; attribute nullable boolean nullableBoolean = 32768; attribute nullable bitmap8 nullableBitmap8 = 32769; diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index 5030da10b28f07..9cc4889125e260 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -2578,7 +2578,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "1", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2614,13 +2614,13 @@ "singleton": 0, "bounded": 0, "defaultValue": "", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 }, { - "name": "CalendarType", + "name": "ActiveCalendarType", "code": 1, "mfgCode": null, "side": "server", @@ -2629,7 +2629,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2644,7 +2644,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2659,7 +2659,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2674,7 +2674,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "0", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -2689,7 +2689,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "1", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -6275,7 +6275,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "0", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -6380,7 +6380,7 @@ "singleton": 0, "bounded": 0, "defaultValue": "0", - "reportable": 0, + "reportable": 1, "minInterval": 1, "maxInterval": 65534, "reportableChange": 0 @@ -13618,6 +13618,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "list_fabric_scoped", + "code": 43, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "timed_write_boolean", "code": 48, @@ -13633,6 +13648,36 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "general_error_boolean", + "code": 49, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "cluster_error_boolean", + "code": 50, + "mfgCode": null, + "side": "server", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "unsupported", "code": 255, @@ -14158,6 +14203,21 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "included": 0, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 0, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "ClusterRevision", "code": 65533, @@ -14420,5 +14480,6 @@ "endpointVersion": 1, "deviceIdentifier": 22 } - ] + ], + "log": [] } \ No newline at end of file diff --git a/src/controller/java/zap-generated/CHIPCallbackTypes.h b/src/controller/java/zap-generated/CHIPCallbackTypes.h index ac6a92e8fcc1f5..e800fac4b34e7a 100644 --- a/src/controller/java/zap-generated/CHIPCallbackTypes.h +++ b/src/controller/java/zap-generated/CHIPCallbackTypes.h @@ -1046,6 +1046,10 @@ typedef void (*CHIPTestClusterClusterListLongOctetStringAttributeCallbackType)( void *, const chip::app::Clusters::TestCluster::Attributes::ListLongOctetString::TypeInfo::DecodableType &); typedef void (*CHIPTestClusterClusterTimedWriteBooleanAttributeCallbackType)( void *, chip::app::Clusters::TestCluster::Attributes::TimedWriteBoolean::TypeInfo::DecodableArgType); +typedef void (*CHIPTestClusterClusterGeneralErrorBooleanAttributeCallbackType)( + void *, chip::app::Clusters::TestCluster::Attributes::GeneralErrorBoolean::TypeInfo::DecodableArgType); +typedef void (*CHIPTestClusterClusterClusterErrorBooleanAttributeCallbackType)( + void *, chip::app::Clusters::TestCluster::Attributes::ClusterErrorBoolean::TypeInfo::DecodableArgType); typedef void (*CHIPTestClusterClusterUnsupportedAttributeCallbackType)( void *, chip::app::Clusters::TestCluster::Attributes::Unsupported::TypeInfo::DecodableArgType); typedef void (*CHIPTestClusterClusterNullableBooleanAttributeCallbackType)( diff --git a/src/controller/java/zap-generated/CHIPClusters-JNI.cpp b/src/controller/java/zap-generated/CHIPClusters-JNI.cpp index 74ff4a49e41c95..d2ffd7ea4394ed 100644 --- a/src/controller/java/zap-generated/CHIPClusters-JNI.cpp +++ b/src/controller/java/zap-generated/CHIPClusters-JNI.cpp @@ -26606,6 +26606,80 @@ JNI_METHOD(void, TestClusterCluster, subscribeTimedWriteBooleanAttribute) onSuccess.release(); onFailure.release(); } +JNI_METHOD(void, TestClusterCluster, subscribeGeneralErrorBooleanAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) +{ + chip::DeviceLayer::StackLock lock; + std::unique_ptr onSuccess( + Platform::New(callback, true), chip::Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), chip::Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + TestClusterCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + using TypeInfo = chip::app::Clusters::TestCluster::Attributes::GeneralErrorBoolean::TypeInfo; + auto successFn = chip::Callback::Callback::FromCancelable( + onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + err = cppCluster->SubscribeAttribute(onSuccess->mContext, successFn->mCall, failureFn->mCall, + static_cast(minInterval), static_cast(maxInterval), + CHIPBooleanAttributeCallback::OnSubscriptionEstablished); + VerifyOrReturn(err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error subscribing to attribute", err)); + + onSuccess.release(); + onFailure.release(); +} +JNI_METHOD(void, TestClusterCluster, subscribeClusterErrorBooleanAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) +{ + chip::DeviceLayer::StackLock lock; + std::unique_ptr onSuccess( + Platform::New(callback, true), chip::Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), chip::Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + TestClusterCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + using TypeInfo = chip::app::Clusters::TestCluster::Attributes::ClusterErrorBoolean::TypeInfo; + auto successFn = chip::Callback::Callback::FromCancelable( + onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + err = cppCluster->SubscribeAttribute(onSuccess->mContext, successFn->mCall, failureFn->mCall, + static_cast(minInterval), static_cast(maxInterval), + CHIPBooleanAttributeCallback::OnSubscriptionEstablished); + VerifyOrReturn(err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error subscribing to attribute", err)); + + onSuccess.release(); + onFailure.release(); +} JNI_METHOD(void, TestClusterCluster, subscribeUnsupportedAttribute) (JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint minInterval, jint maxInterval) { diff --git a/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp b/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp index a7bb6833e628a9..98facbf08d9f67 100644 --- a/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp +++ b/src/controller/java/zap-generated/CHIPClustersWrite-JNI.cpp @@ -5476,6 +5476,110 @@ JNI_METHOD(void, TestClusterCluster, writeTimedWriteBooleanAttribute) onFailure.release(); } +JNI_METHOD(void, TestClusterCluster, writeGeneralErrorBooleanAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jobject value, jobject timedWriteTimeoutMs) +{ + chip::DeviceLayer::StackLock lock; + ListFreer listFreer; + using TypeInfo = chip::app::Clusters::TestCluster::Attributes::GeneralErrorBoolean::TypeInfo; + TypeInfo::Type cppValue; + + std::vector> cleanupByteArrays; + std::vector> cleanupStrings; + + cppValue = + static_cast>(chip::JniReferences::GetInstance().BooleanToPrimitive(value)); + + std::unique_ptr onSuccess( + Platform::New(callback), Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + TestClusterCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + auto successFn = chip::Callback::Callback::FromCancelable(onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + if (timedWriteTimeoutMs == nullptr) + { + err = cppCluster->WriteAttribute(cppValue, onSuccess->mContext, successFn->mCall, failureFn->mCall); + } + else + { + err = cppCluster->WriteAttribute(cppValue, onSuccess->mContext, successFn->mCall, failureFn->mCall, + chip::JniReferences::GetInstance().IntegerToPrimitive(timedWriteTimeoutMs)); + } + VerifyOrReturn( + err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error writing attribute", err)); + + onSuccess.release(); + onFailure.release(); +} + +JNI_METHOD(void, TestClusterCluster, writeClusterErrorBooleanAttribute) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jobject value, jobject timedWriteTimeoutMs) +{ + chip::DeviceLayer::StackLock lock; + ListFreer listFreer; + using TypeInfo = chip::app::Clusters::TestCluster::Attributes::ClusterErrorBoolean::TypeInfo; + TypeInfo::Type cppValue; + + std::vector> cleanupByteArrays; + std::vector> cleanupStrings; + + cppValue = + static_cast>(chip::JniReferences::GetInstance().BooleanToPrimitive(value)); + + std::unique_ptr onSuccess( + Platform::New(callback), Platform::Delete); + VerifyOrReturn(onSuccess.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native success callback", CHIP_ERROR_NO_MEMORY)); + + std::unique_ptr onFailure( + Platform::New(callback), Platform::Delete); + VerifyOrReturn(onFailure.get() != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Error creating native failure callback", CHIP_ERROR_NO_MEMORY)); + + CHIP_ERROR err = CHIP_NO_ERROR; + TestClusterCluster * cppCluster = reinterpret_cast(clusterPtr); + VerifyOrReturn(cppCluster != nullptr, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException( + env, callback, "Could not get native cluster", CHIP_ERROR_INCORRECT_STATE)); + + auto successFn = chip::Callback::Callback::FromCancelable(onSuccess->Cancel()); + auto failureFn = chip::Callback::Callback::FromCancelable(onFailure->Cancel()); + + if (timedWriteTimeoutMs == nullptr) + { + err = cppCluster->WriteAttribute(cppValue, onSuccess->mContext, successFn->mCall, failureFn->mCall); + } + else + { + err = cppCluster->WriteAttribute(cppValue, onSuccess->mContext, successFn->mCall, failureFn->mCall, + chip::JniReferences::GetInstance().IntegerToPrimitive(timedWriteTimeoutMs)); + } + VerifyOrReturn( + err == CHIP_NO_ERROR, + chip::AndroidClusterExceptions::GetInstance().ReturnIllegalStateException(env, callback, "Error writing attribute", err)); + + onSuccess.release(); + onFailure.release(); +} + JNI_METHOD(void, TestClusterCluster, writeUnsupportedAttribute) (JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jobject value, jobject timedWriteTimeoutMs) { diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java index f1eb3dc746ad59..8e231e7b1d751e 100644 --- a/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/zap-generated/chip/devicecontroller/ChipClusters.java @@ -13531,6 +13531,42 @@ public void subscribeTimedWriteBooleanAttribute( subscribeTimedWriteBooleanAttribute(chipClusterPtr, callback, minInterval, maxInterval); } + public void readGeneralErrorBooleanAttribute(BooleanAttributeCallback callback) { + readGeneralErrorBooleanAttribute(chipClusterPtr, callback); + } + + public void writeGeneralErrorBooleanAttribute(DefaultClusterCallback callback, Boolean value) { + writeGeneralErrorBooleanAttribute(chipClusterPtr, callback, value, null); + } + + public void writeGeneralErrorBooleanAttribute( + DefaultClusterCallback callback, Boolean value, int timedWriteTimeoutMs) { + writeGeneralErrorBooleanAttribute(chipClusterPtr, callback, value, timedWriteTimeoutMs); + } + + public void subscribeGeneralErrorBooleanAttribute( + BooleanAttributeCallback callback, int minInterval, int maxInterval) { + subscribeGeneralErrorBooleanAttribute(chipClusterPtr, callback, minInterval, maxInterval); + } + + public void readClusterErrorBooleanAttribute(BooleanAttributeCallback callback) { + readClusterErrorBooleanAttribute(chipClusterPtr, callback); + } + + public void writeClusterErrorBooleanAttribute(DefaultClusterCallback callback, Boolean value) { + writeClusterErrorBooleanAttribute(chipClusterPtr, callback, value, null); + } + + public void writeClusterErrorBooleanAttribute( + DefaultClusterCallback callback, Boolean value, int timedWriteTimeoutMs) { + writeClusterErrorBooleanAttribute(chipClusterPtr, callback, value, timedWriteTimeoutMs); + } + + public void subscribeClusterErrorBooleanAttribute( + BooleanAttributeCallback callback, int minInterval, int maxInterval) { + subscribeClusterErrorBooleanAttribute(chipClusterPtr, callback, minInterval, maxInterval); + } + public void readUnsupportedAttribute(BooleanAttributeCallback callback) { readUnsupportedAttribute(chipClusterPtr, callback); } @@ -14671,6 +14707,30 @@ private native void writeTimedWriteBooleanAttribute( private native void subscribeTimedWriteBooleanAttribute( long chipClusterPtr, BooleanAttributeCallback callback, int minInterval, int maxInterval); + private native void readGeneralErrorBooleanAttribute( + long chipClusterPtr, BooleanAttributeCallback callback); + + private native void writeGeneralErrorBooleanAttribute( + long chipClusterPtr, + DefaultClusterCallback callback, + Boolean value, + @Nullable Integer timedWriteTimeoutMs); + + private native void subscribeGeneralErrorBooleanAttribute( + long chipClusterPtr, BooleanAttributeCallback callback, int minInterval, int maxInterval); + + private native void readClusterErrorBooleanAttribute( + long chipClusterPtr, BooleanAttributeCallback callback); + + private native void writeClusterErrorBooleanAttribute( + long chipClusterPtr, + DefaultClusterCallback callback, + Boolean value, + @Nullable Integer timedWriteTimeoutMs); + + private native void subscribeClusterErrorBooleanAttribute( + long chipClusterPtr, BooleanAttributeCallback callback, int minInterval, int maxInterval); + private native void readUnsupportedAttribute( long chipClusterPtr, BooleanAttributeCallback callback); diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java index 705f36262fdcdd..f60562d8a6603d 100644 --- a/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java +++ b/src/controller/java/zap-generated/chip/devicecontroller/ClusterReadMapping.java @@ -5966,6 +5966,34 @@ public Map> getReadAttributeMap() { readTestClusterTimedWriteBooleanCommandParams); readTestClusterInteractionInfo.put( "readTimedWriteBooleanAttribute", readTestClusterTimedWriteBooleanAttributeInteractionInfo); + Map readTestClusterGeneralErrorBooleanCommandParams = + new LinkedHashMap(); + InteractionInfo readTestClusterGeneralErrorBooleanAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.TestClusterCluster) cluster) + .readGeneralErrorBooleanAttribute( + (ChipClusters.BooleanAttributeCallback) callback); + }, + () -> new ClusterInfoMapping.DelegatedBooleanAttributeCallback(), + readTestClusterGeneralErrorBooleanCommandParams); + readTestClusterInteractionInfo.put( + "readGeneralErrorBooleanAttribute", + readTestClusterGeneralErrorBooleanAttributeInteractionInfo); + Map readTestClusterClusterErrorBooleanCommandParams = + new LinkedHashMap(); + InteractionInfo readTestClusterClusterErrorBooleanAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.TestClusterCluster) cluster) + .readClusterErrorBooleanAttribute( + (ChipClusters.BooleanAttributeCallback) callback); + }, + () -> new ClusterInfoMapping.DelegatedBooleanAttributeCallback(), + readTestClusterClusterErrorBooleanCommandParams); + readTestClusterInteractionInfo.put( + "readClusterErrorBooleanAttribute", + readTestClusterClusterErrorBooleanAttributeInteractionInfo); Map readTestClusterUnsupportedCommandParams = new LinkedHashMap(); InteractionInfo readTestClusterUnsupportedAttributeInteractionInfo = diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ClusterWriteMapping.java b/src/controller/java/zap-generated/chip/devicecontroller/ClusterWriteMapping.java index 04df1c40eedd72..6f8a07f65c856d 100644 --- a/src/controller/java/zap-generated/chip/devicecontroller/ClusterWriteMapping.java +++ b/src/controller/java/zap-generated/chip/devicecontroller/ClusterWriteMapping.java @@ -1568,6 +1568,42 @@ public Map> getWriteAttributeMap() { writeTestClusterInteractionInfo.put( "writeTimedWriteBooleanAttribute", writeTestClusterTimedWriteBooleanAttributeInteractionInfo); + Map writeTestClusterGeneralErrorBooleanCommandParams = + new LinkedHashMap(); + CommandParameterInfo testClustergeneralErrorBooleanCommandParameterInfo = + new CommandParameterInfo("value", Boolean.class); + writeTestClusterGeneralErrorBooleanCommandParams.put( + "value", testClustergeneralErrorBooleanCommandParameterInfo); + InteractionInfo writeTestClusterGeneralErrorBooleanAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.TestClusterCluster) cluster) + .writeGeneralErrorBooleanAttribute( + (DefaultClusterCallback) callback, (Boolean) commandArguments.get("value")); + }, + () -> new ClusterInfoMapping.DelegatedDefaultClusterCallback(), + writeTestClusterGeneralErrorBooleanCommandParams); + writeTestClusterInteractionInfo.put( + "writeGeneralErrorBooleanAttribute", + writeTestClusterGeneralErrorBooleanAttributeInteractionInfo); + Map writeTestClusterClusterErrorBooleanCommandParams = + new LinkedHashMap(); + CommandParameterInfo testClusterclusterErrorBooleanCommandParameterInfo = + new CommandParameterInfo("value", Boolean.class); + writeTestClusterClusterErrorBooleanCommandParams.put( + "value", testClusterclusterErrorBooleanCommandParameterInfo); + InteractionInfo writeTestClusterClusterErrorBooleanAttributeInteractionInfo = + new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.TestClusterCluster) cluster) + .writeClusterErrorBooleanAttribute( + (DefaultClusterCallback) callback, (Boolean) commandArguments.get("value")); + }, + () -> new ClusterInfoMapping.DelegatedDefaultClusterCallback(), + writeTestClusterClusterErrorBooleanCommandParams); + writeTestClusterInteractionInfo.put( + "writeClusterErrorBooleanAttribute", + writeTestClusterClusterErrorBooleanAttributeInteractionInfo); Map writeTestClusterUnsupportedCommandParams = new LinkedHashMap(); CommandParameterInfo testClusterunsupportedCommandParameterInfo = diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 9eb0fce503667a..2efae0bb4d84d9 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -4502,6 +4502,20 @@ class ChipClusters: "reportable": True, "writable": True, }, + 0x00000031: { + "attributeName": "GeneralErrorBoolean", + "attributeId": 0x00000031, + "type": "bool", + "reportable": True, + "writable": True, + }, + 0x00000032: { + "attributeName": "ClusterErrorBoolean", + "attributeId": 0x00000032, + "type": "bool", + "reportable": True, + "writable": True, + }, 0x000000FF: { "attributeName": "Unsupported", "attributeId": 0x000000FF, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 50d11744eca07c..b66e5a9f8103ad 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -29821,6 +29821,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="listLongOctetString", Tag=0x0000002A, Type=typing.List[bytes]), ClusterObjectFieldDescriptor(Label="listFabricScoped", Tag=0x0000002B, Type=typing.List[TestCluster.Structs.TestFabricScoped]), ClusterObjectFieldDescriptor(Label="timedWriteBoolean", Tag=0x00000030, Type=bool), + ClusterObjectFieldDescriptor(Label="generalErrorBoolean", Tag=0x00000031, Type=bool), + ClusterObjectFieldDescriptor(Label="clusterErrorBoolean", Tag=0x00000032, Type=bool), ClusterObjectFieldDescriptor(Label="unsupported", Tag=0x000000FF, Type=bool), ClusterObjectFieldDescriptor(Label="nullableBoolean", Tag=0x00008000, Type=typing.Union[Nullable, bool]), ClusterObjectFieldDescriptor(Label="nullableBitmap8", Tag=0x00008001, Type=typing.Union[Nullable, uint]), @@ -29905,6 +29907,8 @@ def descriptor(cls) -> ClusterObjectDescriptor: listLongOctetString: 'typing.List[bytes]' = None listFabricScoped: 'typing.List[TestCluster.Structs.TestFabricScoped]' = None timedWriteBoolean: 'bool' = None + generalErrorBoolean: 'bool' = None + clusterErrorBoolean: 'bool' = None unsupported: 'bool' = None nullableBoolean: 'typing.Union[Nullable, bool]' = None nullableBitmap8: 'typing.Union[Nullable, uint]' = None @@ -31398,6 +31402,38 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'bool' = False + @dataclass + class GeneralErrorBoolean(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x050F + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000031 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=bool) + + value: 'bool' = False + + @dataclass + class ClusterErrorBoolean(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x050F + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000032 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=bool) + + value: 'bool' = False + @dataclass class Unsupported(ClusterAttributeDescriptor): @ChipUtility.classproperty diff --git a/src/controller/tests/data_model/TestWrite.cpp b/src/controller/tests/data_model/TestWrite.cpp index 40ed9bb67c2b4b..274948956792f7 100644 --- a/src/controller/tests/data_model/TestWrite.cpp +++ b/src/controller/tests/data_model/TestWrite.cpp @@ -90,13 +90,13 @@ CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDesc VerifyOrReturnError(i == 4, CHIP_ERROR_INVALID_ARGUMENT); - AttributePathParams attributePathParams(aClusterInfo.mClusterId, aClusterInfo.mEndpointId, aClusterInfo.mAttributeId); - aWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::Success); + ConcreteAttributePath attributePath(aClusterInfo.mClusterId, aClusterInfo.mEndpointId, aClusterInfo.mAttributeId); + aWriteHandler->AddStatus(attributePath, Protocols::InteractionModel::Status::Success); } else { - AttributePathParams attributePathParams(aClusterInfo.mClusterId, aClusterInfo.mEndpointId, aClusterInfo.mAttributeId); - aWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::Failure); + ConcreteAttributePath attributePath(aClusterInfo.mClusterId, aClusterInfo.mEndpointId, aClusterInfo.mAttributeId); + aWriteHandler->AddStatus(attributePath, Protocols::InteractionModel::Status::Failure); } return CHIP_NO_ERROR; diff --git a/src/darwin/Framework/CHIP/CHIPError.h b/src/darwin/Framework/CHIP/CHIPError.h index 1c4c2ba5304ff1..883d38f5e83402 100644 --- a/src/darwin/Framework/CHIP/CHIPError.h +++ b/src/darwin/Framework/CHIP/CHIPError.h @@ -37,6 +37,7 @@ typedef NS_ERROR_ENUM(CHIPErrorDomain, CHIPErrorCode){ CHIPErrorCodeUnsupportedAttribute = 0x86, CHIPErrorCodeConstraintError = 0x87, CHIPErrorCodeUnsupportedWrite = 0x88, + CHIPErrorCodeInvalidDataType = 0x8D, CHIPErrorCodeUnsupportedCluster = 0xC3, }; // clang-format on diff --git a/src/darwin/Framework/CHIP/CHIPError.mm b/src/darwin/Framework/CHIP/CHIPError.mm index 47fae0d0e87d5d..776acdfe61ee5d 100644 --- a/src/darwin/Framework/CHIP/CHIPError.mm +++ b/src/darwin/Framework/CHIP/CHIPError.mm @@ -128,6 +128,11 @@ + (NSError *)errorForZCLErrorCode:(uint8_t)errorCode errorWithDomain:CHIPErrorDomain code:CHIPErrorCodeUnsupportedWrite userInfo:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Attempt to write read-only attribute.", nil) }]; + case EMBER_ZCL_STATUS_INVALID_DATA_TYPE: + return [NSError + errorWithDomain:CHIPErrorDomain + code:CHIPErrorCodeInvalidDataType + userInfo:@{ NSLocalizedDescriptionKey : NSLocalizedString(@"Data type is not correct for a field.", nil) }]; case EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER: return [NSError errorWithDomain:CHIPErrorDomain diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm index a39953a0c5992c..33451ed2d5128a 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm @@ -7131,6 +7131,28 @@ id CHIPDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::TLVReader value = [NSNumber numberWithBool:cppValue]; return value; } + case Attributes::GeneralErrorBoolean::Id: { + using TypeInfo = Attributes::GeneralErrorBoolean::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithBool:cppValue]; + return value; + } + case Attributes::ClusterErrorBoolean::Id: { + using TypeInfo = Attributes::ClusterErrorBoolean::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithBool:cppValue]; + return value; + } case Attributes::Unsupported::Id: { using TypeInfo = Attributes::Unsupported::TypeInfo; TypeInfo::DecodableType cppValue; diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h index 3b4e0e28db5768..0ed67303418d4c 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.h @@ -4336,6 +4336,26 @@ NS_ASSUME_NONNULL_BEGIN reportHandler: (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; +- (void)readAttributeGeneralErrorBooleanWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler; +- (void)writeAttributeGeneralErrorBooleanWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; +- (void)subscribeAttributeGeneralErrorBooleanWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished: + (SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; + +- (void)readAttributeClusterErrorBooleanWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler; +- (void)writeAttributeClusterErrorBooleanWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; +- (void)subscribeAttributeClusterErrorBooleanWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished: + (SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler; + - (void)readAttributeUnsupportedWithCompletionHandler:(void (^)( NSNumber * _Nullable value, NSError * _Nullable error))completionHandler; - (void)writeAttributeUnsupportedWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler; diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm index 5fdd006a010e3c..53fb76b873117c 100644 --- a/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/CHIPClustersObjc.mm @@ -18866,6 +18866,102 @@ new CHIPBooleanAttributeCallbackSubscriptionBridge( subscriptionEstablishedHandler); } +- (void)readAttributeGeneralErrorBooleanWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler +{ + new CHIPBooleanAttributeCallbackBridge(self.callbackQueue, completionHandler, ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = TestCluster::Attributes::GeneralErrorBoolean::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.ReadAttribute(successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)writeAttributeGeneralErrorBooleanWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler +{ + new CHIPDefaultSuccessCallbackBridge( + self.callbackQueue, + ^(id _Nullable ignored, NSError * _Nullable error) { + completionHandler(error); + }, + ^(Cancelable * success, Cancelable * failure) { + ListFreer listFreer; + using TypeInfo = TestCluster::Attributes::GeneralErrorBoolean::TypeInfo; + TypeInfo::Type cppValue; + cppValue = value.boolValue; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.WriteAttribute(cppValue, successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)subscribeAttributeGeneralErrorBooleanWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished: + (SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + new CHIPBooleanAttributeCallbackSubscriptionBridge( + self.callbackQueue, reportHandler, + ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = TestCluster::Attributes::GeneralErrorBoolean::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.SubscribeAttribute(successFn->mContext, successFn->mCall, failureFn->mCall, + minInterval, maxInterval, CHIPBooleanAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished); + }, + subscriptionEstablishedHandler); +} + +- (void)readAttributeClusterErrorBooleanWithCompletionHandler:(void (^)(NSNumber * _Nullable value, + NSError * _Nullable error))completionHandler +{ + new CHIPBooleanAttributeCallbackBridge(self.callbackQueue, completionHandler, ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = TestCluster::Attributes::ClusterErrorBoolean::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.ReadAttribute(successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)writeAttributeClusterErrorBooleanWithValue:(NSNumber * _Nonnull)value completionHandler:(StatusCompletion)completionHandler +{ + new CHIPDefaultSuccessCallbackBridge( + self.callbackQueue, + ^(id _Nullable ignored, NSError * _Nullable error) { + completionHandler(error); + }, + ^(Cancelable * success, Cancelable * failure) { + ListFreer listFreer; + using TypeInfo = TestCluster::Attributes::ClusterErrorBoolean::TypeInfo; + TypeInfo::Type cppValue; + cppValue = value.boolValue; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.WriteAttribute(cppValue, successFn->mContext, successFn->mCall, failureFn->mCall); + }); +} + +- (void)subscribeAttributeClusterErrorBooleanWithMinInterval:(uint16_t)minInterval + maxInterval:(uint16_t)maxInterval + subscriptionEstablished: + (SubscriptionEstablishedHandler _Nullable)subscriptionEstablishedHandler + reportHandler: + (void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + new CHIPBooleanAttributeCallbackSubscriptionBridge( + self.callbackQueue, reportHandler, + ^(Cancelable * success, Cancelable * failure) { + using TypeInfo = TestCluster::Attributes::ClusterErrorBoolean::TypeInfo; + auto successFn = Callback::FromCancelable(success); + auto failureFn = Callback::FromCancelable(failure); + return self.cppCluster.SubscribeAttribute(successFn->mContext, successFn->mCall, failureFn->mCall, + minInterval, maxInterval, CHIPBooleanAttributeCallbackSubscriptionBridge::OnSubscriptionEstablished); + }, + subscriptionEstablishedHandler); +} + - (void)readAttributeUnsupportedWithCompletionHandler:(void (^)( NSNumber * _Nullable value, NSError * _Nullable error))completionHandler { diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index aee830b46e5bba..0a427ba2b96d9d 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -37010,6 +37010,87 @@ - (void)testSendClusterTestCluster_000471_ReadAttribute [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterTestCluster_000472_WriteAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Write attribute that returns general status on write"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestTestCluster * cluster = [[CHIPTestTestCluster alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + id generalErrorBooleanArgument; + generalErrorBooleanArgument = [NSNumber numberWithBool:false]; + [cluster writeAttributeGeneralErrorBooleanWithValue:generalErrorBooleanArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Write attribute that returns general status on write Error: %@", err); + + XCTAssertEqual( + [CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_INVALID_DATA_TYPE); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestCluster_000473_WriteAttribute +{ + XCTestExpectation * expectation = + [self expectationWithDescription:@"Write attribute that returns cluster-specific status on write"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestTestCluster * cluster = [[CHIPTestTestCluster alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + id clusterErrorBooleanArgument; + clusterErrorBooleanArgument = [NSNumber numberWithBool:false]; + [cluster writeAttributeClusterErrorBooleanWithValue:clusterErrorBooleanArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Write attribute that returns cluster-specific status on write Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_FAILURE); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestCluster_000474_ReadAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Read attribute that returns general status on read"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestTestCluster * cluster = [[CHIPTestTestCluster alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeGeneralErrorBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read attribute that returns general status on read Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_INVALID_DATA_TYPE); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestCluster_000475_ReadAttribute +{ + XCTestExpectation * expectation = + [self expectationWithDescription:@"read attribute that returns cluster-specific status on read"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestTestCluster * cluster = [[CHIPTestTestCluster alloc] initWithDevice:device endpoint:1 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeClusterErrorBooleanWithCompletionHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) { + NSLog(@"read attribute that returns cluster-specific status on read Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], EMBER_ZCL_STATUS_FAILURE); + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} - (void)testSendClusterTestSaveAs_000000_WaitForCommissionee { diff --git a/src/darwin/Framework/CHIPTests/CHIPErrorTestUtils.mm b/src/darwin/Framework/CHIPTests/CHIPErrorTestUtils.mm index 585a743c81dc84..a1674fcfc13810 100644 --- a/src/darwin/Framework/CHIPTests/CHIPErrorTestUtils.mm +++ b/src/darwin/Framework/CHIPTests/CHIPErrorTestUtils.mm @@ -52,6 +52,8 @@ + (uint8_t)errorToZCLErrorCode:(NSError * _Nullable)error return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; case CHIPErrorCodeUnsupportedWrite: return EMBER_ZCL_STATUS_UNSUPPORTED_WRITE; + case CHIPErrorCodeInvalidDataType: + return EMBER_ZCL_STATUS_INVALID_DATA_TYPE; case CHIPErrorCodeUnsupportedCluster: return EMBER_ZCL_STATUS_UNSUPPORTED_CLUSTER; default: diff --git a/src/messaging/ExchangeContext.cpp b/src/messaging/ExchangeContext.cpp index 6757341ecc56c0..a2dc5cbfa75dc7 100644 --- a/src/messaging/ExchangeContext.cpp +++ b/src/messaging/ExchangeContext.cpp @@ -133,8 +133,10 @@ CHIP_ERROR ExchangeContext::SendMessage(Protocols::Id protocolId, uint8_t msgTyp // an error arising below. at the end, we have to close it. ExchangeHandle ref(*this); - // If session requires MRP and NoAutoRequestAck send flag is not specificed, request reliable transmission. - bool reliableTransmissionRequested = GetSessionHandle()->RequireMRP() && !sendFlags.Has(SendMessageFlags::kNoAutoRequestAck); + // If session requires MRP, NoAutoRequestAck send flag is not specified and is not a group exchange context, request reliable + // transmission. + bool reliableTransmissionRequested = + GetSessionHandle()->RequireMRP() && !sendFlags.Has(SendMessageFlags::kNoAutoRequestAck) && !IsGroupExchangeContext(); // If a response message is expected... if (sendFlags.Has(SendMessageFlags::kExpectResponse) && !IsGroupExchangeContext()) @@ -226,8 +228,7 @@ void ExchangeContext::Close() VerifyOrDie(mExchangeMgr != nullptr && GetReferenceCount() > 0); #if defined(CHIP_EXCHANGE_CONTEXT_DETAIL_LOGGING) - ChipLogDetail(ExchangeManager, "ec id: %d [" ChipLogFormatExchange "], %s", (this - mExchangeMgr->mContextPool.begin()), - ChipLogValueExchange(this), __func__); + ChipLogDetail(ExchangeManager, "ec - close[" ChipLogFormatExchange "], %s", ChipLogValueExchange(this), __func__); #endif DoClose(false); @@ -243,8 +244,7 @@ void ExchangeContext::Abort() VerifyOrDie(mExchangeMgr != nullptr && GetReferenceCount() > 0); #if defined(CHIP_EXCHANGE_CONTEXT_DETAIL_LOGGING) - ChipLogDetail(ExchangeManager, "ec id: %d [" ChipLogFormatExchange "], %s", (this - mExchangeMgr->mContextPool.begin()), - ChipLogValueExchange(this), __func__); + ChipLogDetail(ExchangeManager, "ec - abort[" ChipLogFormatExchange "], %s", ChipLogValueExchange(this), __func__); #endif DoClose(true); diff --git a/src/messaging/tests/MessagingContext.cpp b/src/messaging/tests/MessagingContext.cpp index 39d1c51070e533..05be52b6ef008a 100644 --- a/src/messaging/tests/MessagingContext.cpp +++ b/src/messaging/tests/MessagingContext.cpp @@ -82,7 +82,7 @@ CHIP_ERROR MessagingContext::CreateSessionAliceToBob() CHIP_ERROR MessagingContext::CreateSessionBobToFriends() { - mSessionBobToFriends.Grab(mSessionManager.CreateGroupSession(GetFriendsGroupId()).Value()); + mSessionBobToFriends.Grab(mSessionManager.CreateGroupSession(GetFriendsGroupId(), mSrcFabricIndex).Value()); return CHIP_NO_ERROR; } @@ -113,7 +113,7 @@ void MessagingContext::ExpireSessionAliceToBob() void MessagingContext::ExpireSessionBobToFriends() { - // TODO: expire the group session + mSessionManager.RemoveGroupSession(mSessionBobToFriends.Get()->AsGroupSession()); } Messaging::ExchangeContext * MessagingContext::NewUnauthenticatedExchangeToAlice(Messaging::ExchangeDelegate * delegate) diff --git a/src/messaging/tests/MessagingContext.h b/src/messaging/tests/MessagingContext.h index 768fde0abb26f5..cc99415e729029 100644 --- a/src/messaging/tests/MessagingContext.h +++ b/src/messaging/tests/MessagingContext.h @@ -128,8 +128,8 @@ class MessagingContext SessionHolder mSessionAliceToBob; SessionHolder mSessionBobToAlice; SessionHolder mSessionBobToFriends; - FabricIndex mSrcFabricIndex = 0; - FabricIndex mDestFabricIndex = 0; + FabricIndex mSrcFabricIndex = 1; + FabricIndex mDestFabricIndex = 1; }; template diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index 2aca1cdcaf8445..8397aefe1b8c58 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -617,7 +617,9 @@ void SessionManager::SecureGroupMessageDispatch(const PacketHeader & packetHeade if (mCB != nullptr) { - Optional session = CreateGroupSession(packetHeader.GetDestinationGroupId().Value()); + // TODO : remove hard coded fabric index once GroupDataProvider->Decrypt is implemented + Optional session = CreateGroupSession(packetHeader.GetDestinationGroupId().Value(), 1); + VerifyOrReturn(session.HasValue(), ChipLogError(Inet, "Error when creating group session handle.")); Transport::GroupSession * groupSession = session.Value()->AsGroupSession(); diff --git a/src/transport/SessionManager.h b/src/transport/SessionManager.h index b7005854f6e64d..7d30ba0f2364cf 100644 --- a/src/transport/SessionManager.h +++ b/src/transport/SessionManager.h @@ -210,8 +210,14 @@ class DLL_EXPORT SessionManager : public TransportMgrDelegate } // TODO: implements group sessions - Optional CreateGroupSession(GroupId group) { return mGroupSessions.AllocEntry(group, kUndefinedFabricIndex); } - Optional FindGroupSession(GroupId group) { return mGroupSessions.FindEntry(group, kUndefinedFabricIndex); } + Optional CreateGroupSession(GroupId group, chip::FabricIndex fabricIndex) + { + return mGroupSessions.AllocEntry(group, fabricIndex); + } + Optional FindGroupSession(GroupId group, chip::FabricIndex fabricIndex) + { + return mGroupSessions.FindEntry(group, fabricIndex); + } void RemoveGroupSession(Transport::GroupSession * session) { mGroupSessions.DeleteEntry(session); } // TODO: this is a temporary solution for legacy tests which use nodeId to send packets diff --git a/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h b/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h index 6f22cff1c26495..4e9e49d90fc4f0 100644 --- a/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h +++ b/zzz_generated/all-clusters-app/zap-generated/endpoint_config.h @@ -1499,7 +1499,7 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 620 +#define GENERATED_ATTRIBUTE_COUNT 622 #define GENERATED_ATTRIBUTES \ { \ \ @@ -2293,6 +2293,10 @@ ZAP_EMPTY_DEFAULT() }, /* list_fabric_scoped */ \ { 0x00000030, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(MUST_USE_TIMED_WRITE), \ ZAP_EMPTY_DEFAULT() }, /* timed_write_boolean */ \ + { 0x00000031, ZAP_TYPE(BOOLEAN), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* general_error_boolean */ \ + { 0x00000032, ZAP_TYPE(BOOLEAN), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE) | ZAP_ATTRIBUTE_MASK(WRITABLE), \ + ZAP_EMPTY_DEFAULT() }, /* cluster_error_boolean */ \ { 0x00008000, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ ZAP_SIMPLE_DEFAULT(false) }, /* nullable_boolean */ \ { 0x00008001, ZAP_TYPE(BITMAP8), 1, ZAP_ATTRIBUTE_MASK(WRITABLE) | ZAP_ATTRIBUTE_MASK(NULLABLE), \ @@ -2734,28 +2738,28 @@ 0x0000050E, ZAP_ATTRIBUTE_INDEX(510), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Account Login (server) */ \ { \ - 0x0000050F, ZAP_ATTRIBUTE_INDEX(511), 79, 3285, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000050F, ZAP_ATTRIBUTE_INDEX(511), 81, 3285, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Test Cluster (server) */ \ { \ - 0x00000B04, ZAP_ATTRIBUTE_INDEX(590), 12, 28, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000B04, ZAP_ATTRIBUTE_INDEX(592), 12, 28, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Electrical Measurement (server) */ \ { 0x00000004, \ - ZAP_ATTRIBUTE_INDEX(602), \ + ZAP_ATTRIBUTE_INDEX(604), \ 2, \ 3, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayGroupsServer }, /* Endpoint: 2, Cluster: Groups (server) */ \ { 0x00000006, \ - ZAP_ATTRIBUTE_INDEX(604), \ + ZAP_ATTRIBUTE_INDEX(606), \ 7, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 2, Cluster: On/Off (server) */ \ { \ - 0x0000001D, ZAP_ATTRIBUTE_INDEX(611), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000001D, ZAP_ATTRIBUTE_INDEX(613), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 2, Cluster: Descriptor (server) */ \ { 0x00000406, \ - ZAP_ATTRIBUTE_INDEX(616), \ + ZAP_ATTRIBUTE_INDEX(618), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ diff --git a/zzz_generated/app-common/app-common/zap-generated/attribute-id.h b/zzz_generated/app-common/app-common/zap-generated/attribute-id.h index b5c25b8a5fcf8d..cae3e77266e600 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attribute-id.h +++ b/zzz_generated/app-common/app-common/zap-generated/attribute-id.h @@ -1504,6 +1504,8 @@ #define ZCL_LIST_LONG_OCTET_STRING_ATTRIBUTE_ID (0x002A) #define ZCL_LIST_FABRIC_SCOPED_ATTRIBUTE_ID (0x002B) #define ZCL_TIMED_WRITE_BOOLEAN_ATTRIBUTE_ID (0x0030) +#define ZCL_GENERAL_ERROR_BOOLEAN_ATTRIBUTE_ID (0x0031) +#define ZCL_CLUSTER_ERROR_BOOLEAN_ATTRIBUTE_ID (0x0032) #define ZCL_UNSUPPORTED_ATTRIBUTE_ID (0x00FF) #define ZCL_NULLABLE_BOOLEAN_ATTRIBUTE_ID (0x8000) #define ZCL_NULLABLE_BITMAP8_ATTRIBUTE_ID (0x8001) diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index 0810ceddde561b..40abe2f017d48d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -32070,6 +32070,68 @@ EmberAfStatus Set(chip::EndpointId endpoint, bool value) } // namespace TimedWriteBoolean +namespace GeneralErrorBoolean { + +EmberAfStatus Get(chip::EndpointId endpoint, bool * value) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType temp; + uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); + EmberAfStatus status = emberAfReadServerAttribute(endpoint, Clusters::TestCluster::Id, Id, readable, sizeof(temp)); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); + if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) + { + return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; + } + *value = Traits::StorageToWorking(temp); + return status; +} +EmberAfStatus Set(chip::EndpointId endpoint, bool value) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteServerAttribute(endpoint, Clusters::TestCluster::Id, Id, writable, ZCL_BOOLEAN_ATTRIBUTE_TYPE); +} + +} // namespace GeneralErrorBoolean + +namespace ClusterErrorBoolean { + +EmberAfStatus Get(chip::EndpointId endpoint, bool * value) +{ + using Traits = NumericAttributeTraits; + Traits::StorageType temp; + uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); + EmberAfStatus status = emberAfReadServerAttribute(endpoint, Clusters::TestCluster::Id, Id, readable, sizeof(temp)); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); + if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) + { + return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; + } + *value = Traits::StorageToWorking(temp); + return status; +} +EmberAfStatus Set(chip::EndpointId endpoint, bool value) +{ + using Traits = NumericAttributeTraits; + if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) + { + return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; + } + Traits::StorageType storageValue; + Traits::WorkingToStorage(value, storageValue); + uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); + return emberAfWriteServerAttribute(endpoint, Clusters::TestCluster::Id, Id, writable, ZCL_BOOLEAN_ATTRIBUTE_TYPE); +} + +} // namespace ClusterErrorBoolean + namespace Unsupported { EmberAfStatus Get(chip::EndpointId endpoint, bool * value) diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index 8a56f0319eefcf..7754bb5ab3410d 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -5651,6 +5651,16 @@ EmberAfStatus Get(chip::EndpointId endpoint, bool * value); // boolean EmberAfStatus Set(chip::EndpointId endpoint, bool value); } // namespace TimedWriteBoolean +namespace GeneralErrorBoolean { +EmberAfStatus Get(chip::EndpointId endpoint, bool * value); // boolean +EmberAfStatus Set(chip::EndpointId endpoint, bool value); +} // namespace GeneralErrorBoolean + +namespace ClusterErrorBoolean { +EmberAfStatus Get(chip::EndpointId endpoint, bool * value); // boolean +EmberAfStatus Set(chip::EndpointId endpoint, bool value); +} // namespace ClusterErrorBoolean + namespace Unsupported { EmberAfStatus Get(chip::EndpointId endpoint, bool * value); // boolean EmberAfStatus Set(chip::EndpointId endpoint, bool value); diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index dbf2ae0d1cb7d4..d462126bed1946 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -23484,6 +23484,12 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre case Attributes::TimedWriteBoolean::TypeInfo::GetAttributeId(): ReturnErrorOnFailure(DataModel::Decode(reader, timedWriteBoolean)); break; + case Attributes::GeneralErrorBoolean::TypeInfo::GetAttributeId(): + ReturnErrorOnFailure(DataModel::Decode(reader, generalErrorBoolean)); + break; + case Attributes::ClusterErrorBoolean::TypeInfo::GetAttributeId(): + ReturnErrorOnFailure(DataModel::Decode(reader, clusterErrorBoolean)); + break; case Attributes::Unsupported::TypeInfo::GetAttributeId(): ReturnErrorOnFailure(DataModel::Decode(reader, unsupported)); break; diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index 7b106d73f87dad..b46c1cbef6488c 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -35559,6 +35559,30 @@ struct TypeInfo static constexpr bool MustUseTimedWrite() { return true; } }; } // namespace TimedWriteBoolean +namespace GeneralErrorBoolean { +struct TypeInfo +{ + using Type = bool; + using DecodableType = bool; + using DecodableArgType = bool; + + static constexpr ClusterId GetClusterId() { return Clusters::TestCluster::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::GeneralErrorBoolean::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace GeneralErrorBoolean +namespace ClusterErrorBoolean { +struct TypeInfo +{ + using Type = bool; + using DecodableType = bool; + using DecodableArgType = bool; + + static constexpr ClusterId GetClusterId() { return Clusters::TestCluster::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::ClusterErrorBoolean::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace ClusterErrorBoolean namespace Unsupported { struct TypeInfo { @@ -36057,8 +36081,10 @@ struct TypeInfo Attributes::RangeRestrictedInt16s::TypeInfo::DecodableType rangeRestrictedInt16s = static_cast(0); Attributes::ListLongOctetString::TypeInfo::DecodableType listLongOctetString; Attributes::ListFabricScoped::TypeInfo::DecodableType listFabricScoped; - Attributes::TimedWriteBoolean::TypeInfo::DecodableType timedWriteBoolean = static_cast(0); - Attributes::Unsupported::TypeInfo::DecodableType unsupported = static_cast(0); + Attributes::TimedWriteBoolean::TypeInfo::DecodableType timedWriteBoolean = static_cast(0); + Attributes::GeneralErrorBoolean::TypeInfo::DecodableType generalErrorBoolean = static_cast(0); + Attributes::ClusterErrorBoolean::TypeInfo::DecodableType clusterErrorBoolean = static_cast(0); + Attributes::Unsupported::TypeInfo::DecodableType unsupported = static_cast(0); Attributes::NullableBoolean::TypeInfo::DecodableType nullableBoolean; Attributes::NullableBitmap8::TypeInfo::DecodableType nullableBitmap8; Attributes::NullableBitmap16::TypeInfo::DecodableType nullableBitmap16; diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h index 6db88919c598c5..81e1fe13726633 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h @@ -5280,6 +5280,14 @@ namespace TimedWriteBoolean { static constexpr AttributeId Id = 0x00000030; } // namespace TimedWriteBoolean +namespace GeneralErrorBoolean { +static constexpr AttributeId Id = 0x00000031; +} // namespace GeneralErrorBoolean + +namespace ClusterErrorBoolean { +static constexpr AttributeId Id = 0x00000032; +} // namespace ClusterErrorBoolean + namespace Unsupported { static constexpr AttributeId Id = 0x000000FF; } // namespace Unsupported diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 99435cfb2ffc72..79c2a9406a29f5 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -41752,6 +41752,8 @@ class ReportTemperatureMeasurementClusterRevision : public ModelCommand | * RangeRestrictedInt16s | 0x0029 | | * ListLongOctetString | 0x002A | | * TimedWriteBoolean | 0x0030 | +| * GeneralErrorBoolean | 0x0031 | +| * ClusterErrorBoolean | 0x0032 | | * Unsupported | 0x00FF | | * NullableBoolean | 0x8000 | | * NullableBitmap8 | 0x8001 | @@ -46265,6 +46267,196 @@ class ReportTestClusterTimedWriteBoolean : public ModelCommand bool mWait; }; +/* + * Attribute GeneralErrorBoolean + */ +class ReadTestClusterGeneralErrorBoolean : public ModelCommand +{ +public: + ReadTestClusterGeneralErrorBoolean() : ModelCommand("read") + { + AddArgument("attr-name", "general-error-boolean"); + ModelCommand::AddArguments(); + } + + ~ReadTestClusterGeneralErrorBoolean() {} + + CHIP_ERROR SendCommand(ChipDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000050F) ReadAttribute (0x00000031) on endpoint %" PRIu16, endpointId); + + chip::Controller::TestClusterCluster cluster; + cluster.Associate(device, endpointId); + return cluster.ReadAttribute( + this, OnAttributeResponse, OnDefaultFailure); + } + + static void OnAttributeResponse(void * context, bool value) + { + OnGeneralAttributeEventResponse(context, "TestCluster.GeneralErrorBoolean response", value); + } +}; + +class WriteTestClusterGeneralErrorBoolean : public ModelCommand +{ +public: + WriteTestClusterGeneralErrorBoolean() : ModelCommand("write") + { + AddArgument("attr-name", "general-error-boolean"); + AddArgument("attr-value", 0, 1, &mValue); + ModelCommand::AddArguments(); + } + + ~WriteTestClusterGeneralErrorBoolean() {} + + CHIP_ERROR SendCommand(ChipDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000050F) WriteAttribute (0x00000031) on endpoint %" PRIu16, endpointId); + + chip::Controller::TestClusterCluster cluster; + cluster.Associate(device, endpointId); + return cluster.WriteAttribute( + mValue, this, OnDefaultSuccessResponse, OnDefaultFailure, mTimedInteractionTimeoutMs); + } + +private: + bool mValue; +}; + +class ReportTestClusterGeneralErrorBoolean : public ModelCommand +{ +public: + ReportTestClusterGeneralErrorBoolean() : ModelCommand("report") + { + AddArgument("attr-name", "general-error-boolean"); + AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); + AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); + AddArgument("wait", 0, 1, &mWait); + ModelCommand::AddArguments(); + } + + ~ReportTestClusterGeneralErrorBoolean() {} + + CHIP_ERROR SendCommand(ChipDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000050F) ReportAttribute (0x00000031) on endpoint %" PRIu16, endpointId); + + chip::Controller::TestClusterCluster cluster; + cluster.Associate(device, endpointId); + + auto subscriptionEstablishedCallback = mWait ? OnDefaultSuccessResponseWithoutExit : OnDefaultSuccessResponse; + return cluster.SubscribeAttribute( + this, OnValueReport, OnDefaultFailure, mMinInterval, mMaxInterval, subscriptionEstablishedCallback); + } + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mWait ? UINT16_MAX : 10); + } + + static void OnValueReport(void * context, bool value) { LogValue("TestCluster.GeneralErrorBoolean report", 0, value); } + +private: + uint16_t mMinInterval; + uint16_t mMaxInterval; + bool mWait; +}; + +/* + * Attribute ClusterErrorBoolean + */ +class ReadTestClusterClusterErrorBoolean : public ModelCommand +{ +public: + ReadTestClusterClusterErrorBoolean() : ModelCommand("read") + { + AddArgument("attr-name", "cluster-error-boolean"); + ModelCommand::AddArguments(); + } + + ~ReadTestClusterClusterErrorBoolean() {} + + CHIP_ERROR SendCommand(ChipDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000050F) ReadAttribute (0x00000032) on endpoint %" PRIu16, endpointId); + + chip::Controller::TestClusterCluster cluster; + cluster.Associate(device, endpointId); + return cluster.ReadAttribute( + this, OnAttributeResponse, OnDefaultFailure); + } + + static void OnAttributeResponse(void * context, bool value) + { + OnGeneralAttributeEventResponse(context, "TestCluster.ClusterErrorBoolean response", value); + } +}; + +class WriteTestClusterClusterErrorBoolean : public ModelCommand +{ +public: + WriteTestClusterClusterErrorBoolean() : ModelCommand("write") + { + AddArgument("attr-name", "cluster-error-boolean"); + AddArgument("attr-value", 0, 1, &mValue); + ModelCommand::AddArguments(); + } + + ~WriteTestClusterClusterErrorBoolean() {} + + CHIP_ERROR SendCommand(ChipDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000050F) WriteAttribute (0x00000032) on endpoint %" PRIu16, endpointId); + + chip::Controller::TestClusterCluster cluster; + cluster.Associate(device, endpointId); + return cluster.WriteAttribute( + mValue, this, OnDefaultSuccessResponse, OnDefaultFailure, mTimedInteractionTimeoutMs); + } + +private: + bool mValue; +}; + +class ReportTestClusterClusterErrorBoolean : public ModelCommand +{ +public: + ReportTestClusterClusterErrorBoolean() : ModelCommand("report") + { + AddArgument("attr-name", "cluster-error-boolean"); + AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval); + AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval); + AddArgument("wait", 0, 1, &mWait); + ModelCommand::AddArguments(); + } + + ~ReportTestClusterClusterErrorBoolean() {} + + CHIP_ERROR SendCommand(ChipDevice * device, chip::EndpointId endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000050F) ReportAttribute (0x00000032) on endpoint %" PRIu16, endpointId); + + chip::Controller::TestClusterCluster cluster; + cluster.Associate(device, endpointId); + + auto subscriptionEstablishedCallback = mWait ? OnDefaultSuccessResponseWithoutExit : OnDefaultSuccessResponse; + return cluster.SubscribeAttribute( + this, OnValueReport, OnDefaultFailure, mMinInterval, mMaxInterval, subscriptionEstablishedCallback); + } + + chip::System::Clock::Timeout GetWaitDuration() const override + { + return chip::System::Clock::Seconds16(mWait ? UINT16_MAX : 10); + } + + static void OnValueReport(void * context, bool value) { LogValue("TestCluster.ClusterErrorBoolean report", 0, value); } + +private: + uint16_t mMinInterval; + uint16_t mMaxInterval; + bool mWait; +}; + /* * Attribute Unsupported */ @@ -62367,6 +62559,12 @@ void registerClusterTestCluster(Commands & commands) make_unique(), // make_unique(), // make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // + make_unique(), // make_unique(), // make_unique(), // make_unique(), // diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index dcc177858908c9..d8de862d415113 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -48906,6 +48906,22 @@ class TestCluster : public TestCommand " ***** Test Step 471 : Verify nullable range-restricted signed 16-bit integer value is null\n"); err = TestVerifyNullableRangeRestrictedSigned16BitIntegerValueIsNull_471(); break; + case 472: + ChipLogProgress(chipTool, " ***** Test Step 472 : Write attribute that returns general status on write\n"); + err = TestWriteAttributeThatReturnsGeneralStatusOnWrite_472(); + break; + case 473: + ChipLogProgress(chipTool, " ***** Test Step 473 : Write attribute that returns cluster-specific status on write\n"); + err = TestWriteAttributeThatReturnsClusterSpecificStatusOnWrite_473(); + break; + case 474: + ChipLogProgress(chipTool, " ***** Test Step 474 : Read attribute that returns general status on read\n"); + err = TestReadAttributeThatReturnsGeneralStatusOnRead_474(); + break; + case 475: + ChipLogProgress(chipTool, " ***** Test Step 475 : read attribute that returns cluster-specific status on read\n"); + err = TestReadAttributeThatReturnsClusterSpecificStatusOnRead_475(); + break; } if (CHIP_NO_ERROR != err) @@ -48917,7 +48933,7 @@ class TestCluster : public TestCommand private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 472; + const uint16_t mTestCount = 476; chip::Optional mCluster; chip::Optional mEndpoint; @@ -52787,6 +52803,40 @@ class TestCluster : public TestCommand (static_cast(context))->OnSuccessResponse_471(nullableRangeRestrictedInt16s); } + static void OnFailureCallback_472(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_472(error); + } + + static void OnSuccessCallback_472(void * context) { (static_cast(context))->OnSuccessResponse_472(); } + + static void OnFailureCallback_473(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_473(error); + } + + static void OnSuccessCallback_473(void * context) { (static_cast(context))->OnSuccessResponse_473(); } + + static void OnFailureCallback_474(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_474(error); + } + + static void OnSuccessCallback_474(void * context, bool generalErrorBoolean) + { + (static_cast(context))->OnSuccessResponse_474(generalErrorBoolean); + } + + static void OnFailureCallback_475(void * context, CHIP_ERROR error) + { + (static_cast(context))->OnFailureResponse_475(error); + } + + static void OnSuccessCallback_475(void * context, bool clusterErrorBoolean) + { + (static_cast(context))->OnSuccessResponse_475(clusterErrorBoolean); + } + // // Tests methods // @@ -64783,6 +64833,92 @@ class TestCluster : public TestCommand NextTest(); } + + CHIP_ERROR TestWriteAttributeThatReturnsGeneralStatusOnWrite_472() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + bool generalErrorBooleanArgument; + generalErrorBooleanArgument = false; + + ReturnErrorOnFailure(cluster.WriteAttribute( + generalErrorBooleanArgument, this, OnSuccessCallback_472, OnFailureCallback_472)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_472(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_DATA_TYPE)); + NextTest(); + } + + void OnSuccessResponse_472() { ThrowSuccessResponse(); } + + CHIP_ERROR TestWriteAttributeThatReturnsClusterSpecificStatusOnWrite_473() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + bool clusterErrorBooleanArgument; + clusterErrorBooleanArgument = false; + + ReturnErrorOnFailure(cluster.WriteAttribute( + clusterErrorBooleanArgument, this, OnSuccessCallback_473, OnFailureCallback_473)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_473(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_FAILURE)); + NextTest(); + } + + void OnSuccessResponse_473() { ThrowSuccessResponse(); } + + CHIP_ERROR TestReadAttributeThatReturnsGeneralStatusOnRead_474() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_474, OnFailureCallback_474)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_474(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_INVALID_DATA_TYPE)); + NextTest(); + } + + void OnSuccessResponse_474(bool generalErrorBoolean) { ThrowSuccessResponse(); } + + CHIP_ERROR TestReadAttributeThatReturnsClusterSpecificStatusOnRead_475() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + chip::Controller::TestClusterClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_475, OnFailureCallback_475)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_475(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), EMBER_ZCL_STATUS_FAILURE)); + NextTest(); + } + + void OnSuccessResponse_475(bool clusterErrorBoolean) { ThrowSuccessResponse(); } }; class TestClusterComplexTypes : public TestCommand @@ -73068,28 +73204,37 @@ class TestGroupMessaging : public TestCommand err = TestWaitForTheCommissionedDeviceToBeRetrieved_0(); break; case 1: - ChipLogProgress(chipTool, " ***** Test Step 1 : Group Write Attribute\n"); - err = TestGroupWriteAttribute_1(); + ChipLogProgress(chipTool, " ***** Test Step 1 : Add Group 1 - endpoint 1\n"); + err = TestAddGroup1Endpoint1_1(); break; case 2: - ChipLogProgress(chipTool, " ***** Test Step 2 : Read back Attribute\n"); - err = TestReadBackAttribute_2(); + ChipLogProgress(chipTool, " ***** Test Step 2 : Add Group 2 - endpoint 0\n"); + err = TestAddGroup2Endpoint0_2(); break; case 3: - ChipLogProgress(chipTool, " ***** Test Step 3 : Restore initial location value\n"); - err = TestRestoreInitialLocationValue_3(); + ChipLogProgress(chipTool, " ***** Test Step 3 : Group Write Attribute\n"); + err = TestGroupWriteAttribute_3(); break; case 4: ChipLogProgress(chipTool, " ***** Test Step 4 : Read back Attribute\n"); err = TestReadBackAttribute_4(); break; case 5: - ChipLogProgress(chipTool, " ***** Test Step 5 : Turn On the light to see attribute change\n"); - err = TestTurnOnTheLightToSeeAttributeChange_5(); + ChipLogProgress(chipTool, " ***** Test Step 5 : Restore initial location value\n"); + err = TestRestoreInitialLocationValue_5(); break; case 6: - ChipLogProgress(chipTool, " ***** Test Step 6 : Check on/off attribute value is true after on command\n"); - err = TestCheckOnOffAttributeValueIsTrueAfterOnCommand_6(); + ChipLogProgress(chipTool, " ***** Test Step 6 : Read back Attribute\n"); + err = TestReadBackAttribute_6(); + break; + case 7: + ChipLogProgress(chipTool, " ***** Test Step 7 : Turn On the light to see attribute change\n"); + err = TestTurnOnTheLightToSeeAttributeChange_7(); + break; + case 8: + ChipLogProgress(chipTool, + " ***** Test Step 8 : Check on/off attribute value is true after on command for endpoint 1\n"); + err = TestCheckOnOffAttributeValueIsTrueAfterOnCommandForEndpoint1_8(); break; } @@ -73102,57 +73247,57 @@ class TestGroupMessaging : public TestCommand private: std::atomic_uint16_t mTestIndex; - const uint16_t mTestCount = 7; + const uint16_t mTestCount = 9; chip::Optional mCluster; chip::Optional mEndpoint; - static void OnDoneCallback_1(void * context) { (static_cast(context))->OnDoneResponse_1(); } + static void OnDoneCallback_3(void * context) { (static_cast(context))->OnDoneResponse_3(); } - static void OnFailureCallback_1(void * context, CHIP_ERROR error) + static void OnFailureCallback_3(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_1(error); + (static_cast(context))->OnFailureResponse_3(error); } - static void OnSuccessCallback_1(void * context) { (static_cast(context))->OnSuccessResponse_1(); } + static void OnSuccessCallback_3(void * context) { (static_cast(context))->OnSuccessResponse_3(); } - static void OnFailureCallback_2(void * context, CHIP_ERROR error) + static void OnFailureCallback_4(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_2(error); + (static_cast(context))->OnFailureResponse_4(error); } - static void OnSuccessCallback_2(void * context, chip::CharSpan location) + static void OnSuccessCallback_4(void * context, chip::CharSpan location) { - (static_cast(context))->OnSuccessResponse_2(location); + (static_cast(context))->OnSuccessResponse_4(location); } - static void OnDoneCallback_3(void * context) { (static_cast(context))->OnDoneResponse_3(); } + static void OnDoneCallback_5(void * context) { (static_cast(context))->OnDoneResponse_5(); } - static void OnFailureCallback_3(void * context, CHIP_ERROR error) + static void OnFailureCallback_5(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_3(error); + (static_cast(context))->OnFailureResponse_5(error); } - static void OnSuccessCallback_3(void * context) { (static_cast(context))->OnSuccessResponse_3(); } + static void OnSuccessCallback_5(void * context) { (static_cast(context))->OnSuccessResponse_5(); } - static void OnFailureCallback_4(void * context, CHIP_ERROR error) + static void OnFailureCallback_6(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_4(error); + (static_cast(context))->OnFailureResponse_6(error); } - static void OnSuccessCallback_4(void * context, chip::CharSpan location) + static void OnSuccessCallback_6(void * context, chip::CharSpan location) { - (static_cast(context))->OnSuccessResponse_4(location); + (static_cast(context))->OnSuccessResponse_6(location); } - static void OnFailureCallback_6(void * context, CHIP_ERROR error) + static void OnFailureCallback_8(void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_6(error); + (static_cast(context))->OnFailureResponse_8(error); } - static void OnSuccessCallback_6(void * context, bool onOff) + static void OnSuccessCallback_8(void * context, bool onOff) { - (static_cast(context))->OnSuccessResponse_6(onOff); + (static_cast(context))->OnSuccessResponse_8(onOff); } // @@ -73165,17 +73310,24 @@ class TestGroupMessaging : public TestCommand return WaitForCommissionee(); } - CHIP_ERROR TestGroupWriteAttribute_1() + CHIP_ERROR TestAddGroup1Endpoint1_1() { - const chip::GroupId groupId = 1234; - chip::Controller::BasicClusterTest cluster; - cluster.AssociateWithGroup(mDevices[kIdentityAlpha], groupId); + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; + using RequestType = chip::app::Clusters::Groups::Commands::AddGroup::Type; - chip::CharSpan locationArgument; - locationArgument = chip::Span("usgarbage: not in length on purpose", 2); + RequestType request; + request.groupId = 4660U; + request.groupName = chip::Span("Group #1garbage: not in length on purpose", 8); - ReturnErrorOnFailure(cluster.WriteAttribute( - locationArgument, this, OnSuccessCallback_1, OnFailureCallback_1, OnDoneCallback_1)); + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_1(data.status, data.groupId); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_1(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); return CHIP_NO_ERROR; } @@ -73185,18 +73337,33 @@ class TestGroupMessaging : public TestCommand ThrowFailureResponse(); } - void OnSuccessResponse_1() { NextTest(); } + void OnSuccessResponse_1(uint8_t status, uint16_t groupId) + { + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValue("groupId", groupId, 4660U)); - void OnDoneResponse_1() { NextTest(); } + NextTest(); + } - CHIP_ERROR TestReadBackAttribute_2() + CHIP_ERROR TestAddGroup2Endpoint0_2() { const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; - chip::Controller::BasicClusterTest cluster; - cluster.Associate(mDevices[kIdentityAlpha], endpoint); + using RequestType = chip::app::Clusters::Groups::Commands::AddGroup::Type; - ReturnErrorOnFailure(cluster.ReadAttribute( - this, OnSuccessCallback_2, OnFailureCallback_2)); + RequestType request; + request.groupId = 1U; + request.groupName = chip::Span("Group #2garbage: not in length on purpose", 8); + + auto success = [](void * context, const typename RequestType::ResponseType & data) { + (static_cast(context))->OnSuccessResponse_2(data.status, data.groupId); + }; + + auto failure = [](void * context, CHIP_ERROR error) { + (static_cast(context))->OnFailureResponse_2(error); + }; + + ReturnErrorOnFailure(chip::Controller::InvokeCommand(mDevices[kIdentityAlpha], this, success, failure, endpoint, request)); return CHIP_NO_ERROR; } @@ -73206,21 +73373,23 @@ class TestGroupMessaging : public TestCommand ThrowFailureResponse(); } - void OnSuccessResponse_2(chip::CharSpan location) + void OnSuccessResponse_2(uint8_t status, uint16_t groupId) { - VerifyOrReturn(CheckValueAsString("location", location, chip::CharSpan("us", 2))); + VerifyOrReturn(CheckValue("status", status, 0)); + + VerifyOrReturn(CheckValue("groupId", groupId, 1U)); NextTest(); } - CHIP_ERROR TestRestoreInitialLocationValue_3() + CHIP_ERROR TestGroupWriteAttribute_3() { - const chip::GroupId groupId = 1234; + const chip::GroupId groupId = 1; chip::Controller::BasicClusterTest cluster; cluster.AssociateWithGroup(mDevices[kIdentityAlpha], groupId); chip::CharSpan locationArgument; - locationArgument = chip::Span("garbage: not in length on purpose", 0); + locationArgument = chip::Span("usgarbage: not in length on purpose", 2); ReturnErrorOnFailure(cluster.WriteAttribute( locationArgument, this, OnSuccessCallback_3, OnFailureCallback_3, OnDoneCallback_3)); @@ -73255,62 +73424,110 @@ class TestGroupMessaging : public TestCommand } void OnSuccessResponse_4(chip::CharSpan location) + { + VerifyOrReturn(CheckValueAsString("location", location, chip::CharSpan("us", 2))); + + NextTest(); + } + + CHIP_ERROR TestRestoreInitialLocationValue_5() + { + const chip::GroupId groupId = 1; + chip::Controller::BasicClusterTest cluster; + cluster.AssociateWithGroup(mDevices[kIdentityAlpha], groupId); + + chip::CharSpan locationArgument; + locationArgument = chip::Span("garbage: not in length on purpose", 0); + + ReturnErrorOnFailure(cluster.WriteAttribute( + locationArgument, this, OnSuccessCallback_5, OnFailureCallback_5, OnDoneCallback_5)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_5(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_5() { NextTest(); } + + void OnDoneResponse_5() { NextTest(); } + + CHIP_ERROR TestReadBackAttribute_6() + { + const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 0; + chip::Controller::BasicClusterTest cluster; + cluster.Associate(mDevices[kIdentityAlpha], endpoint); + + ReturnErrorOnFailure(cluster.ReadAttribute( + this, OnSuccessCallback_6, OnFailureCallback_6)); + return CHIP_NO_ERROR; + } + + void OnFailureResponse_6(CHIP_ERROR error) + { + chip::app::StatusIB status(error); + ThrowFailureResponse(); + } + + void OnSuccessResponse_6(chip::CharSpan location) { VerifyOrReturn(CheckValueAsString("location", location, chip::CharSpan("", 0))); NextTest(); } - CHIP_ERROR TestTurnOnTheLightToSeeAttributeChange_5() + CHIP_ERROR TestTurnOnTheLightToSeeAttributeChange_7() { - const chip::GroupId groupId = 1234; + const chip::GroupId groupId = 4660; using RequestType = chip::app::Clusters::OnOff::Commands::On::Type; RequestType request; auto success = [](void * context, const typename RequestType::ResponseType & data) { - (static_cast(context))->OnSuccessResponse_5(); + (static_cast(context))->OnSuccessResponse_7(); }; auto failure = [](void * context, CHIP_ERROR error) { - (static_cast(context))->OnFailureResponse_5(error); + (static_cast(context))->OnFailureResponse_7(error); }; - auto done = [](void * context) { (static_cast(context))->OnDoneResponse_5(); }; + auto done = [](void * context) { (static_cast(context))->OnDoneResponse_7(); }; ReturnErrorOnFailure( chip::Controller::InvokeGroupCommand(mDevices[kIdentityAlpha], this, success, failure, done, groupId, request)); return CHIP_NO_ERROR; } - void OnFailureResponse_5(CHIP_ERROR error) + void OnFailureResponse_7(CHIP_ERROR error) { chip::app::StatusIB status(error); ThrowFailureResponse(); } - void OnSuccessResponse_5() { NextTest(); } + void OnSuccessResponse_7() { NextTest(); } - void OnDoneResponse_5() { NextTest(); } + void OnDoneResponse_7() { NextTest(); } - CHIP_ERROR TestCheckOnOffAttributeValueIsTrueAfterOnCommand_6() + CHIP_ERROR TestCheckOnOffAttributeValueIsTrueAfterOnCommandForEndpoint1_8() { const chip::EndpointId endpoint = mEndpoint.HasValue() ? mEndpoint.Value() : 1; chip::Controller::OnOffClusterTest cluster; cluster.Associate(mDevices[kIdentityAlpha], endpoint); ReturnErrorOnFailure(cluster.ReadAttribute( - this, OnSuccessCallback_6, OnFailureCallback_6)); + this, OnSuccessCallback_8, OnFailureCallback_8)); return CHIP_NO_ERROR; } - void OnFailureResponse_6(CHIP_ERROR error) + void OnFailureResponse_8(CHIP_ERROR error) { chip::app::StatusIB status(error); ThrowFailureResponse(); } - void OnSuccessResponse_6(bool onOff) + void OnSuccessResponse_8(bool onOff) { VerifyOrReturn(CheckValue("onOff", onOff, 1)); diff --git a/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp b/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp index f3c22214531d85..0378e5df3ce3d7 100644 --- a/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp +++ b/zzz_generated/lighting-app/zap-generated/IMClusterCommandHandler.cpp @@ -449,6 +449,92 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } // namespace GeneralCommissioning +namespace Groups { + +void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) +{ + // We are using TLVUnpackError and TLVError here since both of them can be CHIP_END_OF_TLV + // When TLVError is CHIP_END_OF_TLV, it means we have iterated all of the items, which is not a real error. + // Any error value TLVUnpackError means we have received an illegal value. + // The following variables are used for all commands to save code size. + CHIP_ERROR TLVError = CHIP_NO_ERROR; + bool wasHandled = false; + { + switch (aCommandPath.mCommandId) + { + case Commands::AddGroup::Id: { + Commands::AddGroup::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterAddGroupCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::AddGroupIfIdentifying::Id: { + Commands::AddGroupIfIdentifying::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterAddGroupIfIdentifyingCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::GetGroupMembership::Id: { + Commands::GetGroupMembership::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterGetGroupMembershipCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RemoveAllGroups::Id: { + Commands::RemoveAllGroups::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterRemoveAllGroupsCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::RemoveGroup::Id: { + Commands::RemoveGroup::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterRemoveGroupCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + case Commands::ViewGroup::Id: { + Commands::ViewGroup::DecodableType commandData; + TLVError = DataModel::Decode(aDataTlv, commandData); + if (TLVError == CHIP_NO_ERROR) + { + wasHandled = emberAfGroupsClusterViewGroupCallback(apCommandObj, aCommandPath, commandData); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, + ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || !wasHandled) + { + apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); + ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); + } +} + +} // namespace Groups + namespace Identify { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) @@ -1280,6 +1366,9 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: case Clusters::GeneralCommissioning::Id: Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; + case Clusters::Groups::Id: + Clusters::Groups::DispatchServerCommand(apCommandObj, aCommandPath, aReader); + break; case Clusters::Identify::Id: Clusters::Identify::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; diff --git a/zzz_generated/lighting-app/zap-generated/PluginApplicationCallbacks.h b/zzz_generated/lighting-app/zap-generated/PluginApplicationCallbacks.h index f558a396382d5e..7efd0d8121b3a9 100644 --- a/zzz_generated/lighting-app/zap-generated/PluginApplicationCallbacks.h +++ b/zzz_generated/lighting-app/zap-generated/PluginApplicationCallbacks.h @@ -31,6 +31,7 @@ MatterFixedLabelPluginServerInitCallback(); \ MatterGeneralCommissioningPluginServerInitCallback(); \ MatterGeneralDiagnosticsPluginServerInitCallback(); \ + MatterGroupsPluginServerInitCallback(); \ MatterIdentifyPluginServerInitCallback(); \ MatterLevelControlPluginServerInitCallback(); \ MatterLocalizationConfigurationPluginServerInitCallback(); \ diff --git a/zzz_generated/lighting-app/zap-generated/callback-stub.cpp b/zzz_generated/lighting-app/zap-generated/callback-stub.cpp index fb97ee9c5583fc..eecb99666c2612 100644 --- a/zzz_generated/lighting-app/zap-generated/callback-stub.cpp +++ b/zzz_generated/lighting-app/zap-generated/callback-stub.cpp @@ -56,6 +56,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_GENERAL_DIAGNOSTICS_CLUSTER_ID: emberAfGeneralDiagnosticsClusterInitCallback(endpoint); break; + case ZCL_GROUPS_CLUSTER_ID: + emberAfGroupsClusterInitCallback(endpoint); + break; case ZCL_IDENTIFY_CLUSTER_ID: emberAfIdentifyClusterInitCallback(endpoint); break; @@ -155,6 +158,11 @@ void __attribute__((weak)) emberAfGeneralDiagnosticsClusterInitCallback(Endpoint // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfGroupsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfIdentifyClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/zzz_generated/lighting-app/zap-generated/endpoint_config.h b/zzz_generated/lighting-app/zap-generated/endpoint_config.h index 509d64ef7b38a3..f7ad9ce8071a79 100644 --- a/zzz_generated/lighting-app/zap-generated/endpoint_config.h +++ b/zzz_generated/lighting-app/zap-generated/endpoint_config.h @@ -612,12 +612,16 @@ #define ZAP_ATTRIBUTE_MASK(mask) ATTRIBUTE_MASK_##mask // This is an array of EmberAfAttributeMetadata structures. -#define GENERATED_ATTRIBUTE_COUNT 236 +#define GENERATED_ATTRIBUTE_COUNT 240 #define GENERATED_ATTRIBUTES \ { \ \ - /* Endpoint: 0, Cluster: Descriptor (server) */ \ - { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* device list */ \ + /* Endpoint: 0, Cluster: Groups (server) */ \ + { 0x00000000, ZAP_TYPE(BITMAP8), 1, 0, ZAP_EMPTY_DEFAULT() }, /* name support */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ + \ + /* Endpoint: 0, Cluster: Descriptor (server) */ \ + { 0x00000000, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* device list */ \ { 0x00000001, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* server list */ \ { 0x00000002, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* client list */ \ { 0x00000003, ZAP_TYPE(ARRAY), 0, ZAP_ATTRIBUTE_MASK(EXTERNAL_STORAGE), ZAP_EMPTY_DEFAULT() }, /* parts list */ \ @@ -852,6 +856,10 @@ { 0x00000001, ZAP_TYPE(ENUM8), 1, 0, ZAP_SIMPLE_DEFAULT(0x0) }, /* identify type */ \ { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(2) }, /* ClusterRevision */ \ \ + /* Endpoint: 1, Cluster: Groups (server) */ \ + { 0x00000000, ZAP_TYPE(BITMAP8), 1, 0, ZAP_EMPTY_DEFAULT() }, /* name support */ \ + { 0x0000FFFD, ZAP_TYPE(INT16U), 2, 0, ZAP_SIMPLE_DEFAULT(3) }, /* ClusterRevision */ \ + \ /* Endpoint: 1, Cluster: On/Off (server) */ \ { 0x00000000, ZAP_TYPE(BOOLEAN), 1, ZAP_ATTRIBUTE_MASK(TOKENIZE), ZAP_SIMPLE_DEFAULT(0x00) }, /* OnOff */ \ { 0x00004000, ZAP_TYPE(BOOLEAN), 1, 0, ZAP_SIMPLE_DEFAULT(0x01) }, /* GlobalSceneControl */ \ @@ -942,6 +950,9 @@ // Cluster function static arrays #define GENERATED_FUNCTION_ARRAYS \ + const EmberAfGenericClusterFunction chipFuncArrayGroupsServer[] = { \ + (EmberAfGenericClusterFunction) emberAfGroupsClusterServerInitCallback, \ + }; \ const EmberAfGenericClusterFunction chipFuncArrayBasicServer[] = { \ (EmberAfGenericClusterFunction) emberAfBasicClusterServerInitCallback, \ }; \ @@ -971,113 +982,125 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 27 +#define GENERATED_CLUSTER_COUNT 29 #define GENERATED_CLUSTERS \ { \ - { \ - 0x0000001D, ZAP_ATTRIBUTE_INDEX(0), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ - }, /* Endpoint: 0, Cluster: Descriptor (server) */ \ + { 0x00000004, \ + ZAP_ATTRIBUTE_INDEX(0), \ + 2, \ + 3, \ + ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ + chipFuncArrayGroupsServer }, /* Endpoint: 0, Cluster: Groups (server) */ \ + { \ + 0x0000001D, ZAP_ATTRIBUTE_INDEX(2), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Descriptor (server) */ \ { 0x00000028, \ - ZAP_ATTRIBUTE_INDEX(5), \ + ZAP_ATTRIBUTE_INDEX(7), \ 20, \ 687, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayBasicServer }, /* Endpoint: 0, Cluster: Basic (server) */ \ { \ - 0x00000029, ZAP_ATTRIBUTE_INDEX(25), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x00000029, ZAP_ATTRIBUTE_INDEX(27), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 0, Cluster: OTA Software Update Provider (client) */ \ { \ - 0x0000002A, ZAP_ATTRIBUTE_INDEX(26), 5, 5, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000002A, ZAP_ATTRIBUTE_INDEX(28), 5, 5, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: OTA Software Update Requestor (server) */ \ { 0x0000002B, \ - ZAP_ATTRIBUTE_INDEX(31), \ + ZAP_ATTRIBUTE_INDEX(33), \ 3, \ 38, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayLocalizationConfigurationServer }, /* Endpoint: 0, Cluster: Localization Configuration (server) */ \ { 0x0000002C, \ - ZAP_ATTRIBUTE_INDEX(34), \ + ZAP_ATTRIBUTE_INDEX(36), \ 4, \ 4, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(PRE_ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayTimeFormatLocalizationServer }, /* Endpoint: 0, Cluster: Time Format Localization (server) */ \ { \ - 0x00000030, ZAP_ATTRIBUTE_INDEX(38), 6, 270, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000030, ZAP_ATTRIBUTE_INDEX(40), 6, 270, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Commissioning (server) */ \ { \ - 0x00000031, ZAP_ATTRIBUTE_INDEX(44), 10, 60, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000031, ZAP_ATTRIBUTE_INDEX(46), 10, 60, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ { \ - 0x00000032, ZAP_ATTRIBUTE_INDEX(54), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000032, ZAP_ATTRIBUTE_INDEX(56), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ - 0x00000033, ZAP_ATTRIBUTE_INDEX(54), 9, 17, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000033, ZAP_ATTRIBUTE_INDEX(56), 9, 17, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ { \ - 0x00000034, ZAP_ATTRIBUTE_INDEX(63), 6, 30, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000034, ZAP_ATTRIBUTE_INDEX(65), 6, 30, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { \ - 0x00000035, ZAP_ATTRIBUTE_INDEX(69), 65, 247, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000035, ZAP_ATTRIBUTE_INDEX(71), 65, 247, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Thread Network Diagnostics (server) */ \ { \ - 0x00000036, ZAP_ATTRIBUTE_INDEX(134), 15, 58, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000036, ZAP_ATTRIBUTE_INDEX(136), 15, 58, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: WiFi Network Diagnostics (server) */ \ { \ - 0x00000037, ZAP_ATTRIBUTE_INDEX(149), 11, 57, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000037, ZAP_ATTRIBUTE_INDEX(151), 11, 57, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Ethernet Network Diagnostics (server) */ \ { \ - 0x0000003B, ZAP_ATTRIBUTE_INDEX(160), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000003B, ZAP_ATTRIBUTE_INDEX(162), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Switch (server) */ \ { \ - 0x0000003C, ZAP_ATTRIBUTE_INDEX(160), 4, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000003C, ZAP_ATTRIBUTE_INDEX(162), 4, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: AdministratorCommissioning (server) */ \ { \ - 0x0000003E, ZAP_ATTRIBUTE_INDEX(164), 7, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000003E, ZAP_ATTRIBUTE_INDEX(166), 7, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Operational Credentials (server) */ \ { \ - 0x00000040, ZAP_ATTRIBUTE_INDEX(171), 2, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000040, ZAP_ATTRIBUTE_INDEX(173), 2, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Fixed Label (server) */ \ { \ - 0x00000041, ZAP_ATTRIBUTE_INDEX(173), 2, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000041, ZAP_ATTRIBUTE_INDEX(175), 2, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: User Label (server) */ \ { 0x00000003, \ - ZAP_ATTRIBUTE_INDEX(175), \ + ZAP_ATTRIBUTE_INDEX(177), \ 3, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION) | ZAP_CLUSTER_MASK(ATTRIBUTE_CHANGED_FUNCTION), \ chipFuncArrayIdentifyServer }, /* Endpoint: 1, Cluster: Identify (server) */ \ + { 0x00000004, \ + ZAP_ATTRIBUTE_INDEX(180), \ + 2, \ + 3, \ + ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ + chipFuncArrayGroupsServer }, /* Endpoint: 1, Cluster: Groups (server) */ \ { 0x00000006, \ - ZAP_ATTRIBUTE_INDEX(178), \ + ZAP_ATTRIBUTE_INDEX(182), \ 7, \ 13, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOnOffServer }, /* Endpoint: 1, Cluster: On/Off (server) */ \ { 0x00000008, \ - ZAP_ATTRIBUTE_INDEX(185), \ + ZAP_ATTRIBUTE_INDEX(189), \ 16, \ 27, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayLevelControlServer }, /* Endpoint: 1, Cluster: Level Control (server) */ \ { \ - 0x0000001D, ZAP_ATTRIBUTE_INDEX(201), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x0000001D, ZAP_ATTRIBUTE_INDEX(205), 5, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 1, Cluster: Descriptor (server) */ \ { 0x00000300, \ - ZAP_ATTRIBUTE_INDEX(206), \ + ZAP_ATTRIBUTE_INDEX(210), \ 22, \ 36, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayColorControlServer }, /* Endpoint: 1, Cluster: Color Control (server) */ \ { 0x00000406, \ - ZAP_ATTRIBUTE_INDEX(228), \ + ZAP_ATTRIBUTE_INDEX(232), \ 4, \ 5, \ ZAP_CLUSTER_MASK(SERVER) | ZAP_CLUSTER_MASK(INIT_FUNCTION), \ chipFuncArrayOccupancySensingServer }, /* Endpoint: 1, Cluster: Occupancy Sensing (server) */ \ { \ - 0x00000006, ZAP_ATTRIBUTE_INDEX(232), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ + 0x00000006, ZAP_ATTRIBUTE_INDEX(236), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 2, Cluster: On/Off (client) */ \ { \ - 0x00000007, ZAP_ATTRIBUTE_INDEX(233), 3, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ + 0x00000007, ZAP_ATTRIBUTE_INDEX(237), 3, 4, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 2, Cluster: On/off Switch Configuration (server) */ \ } @@ -1086,7 +1109,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 19, 1485 }, { ZAP_CLUSTER_INDEX(19), 6, 86 }, { ZAP_CLUSTER_INDEX(25), 2, 6 }, \ + { ZAP_CLUSTER_INDEX(0), 20, 1488 }, { ZAP_CLUSTER_INDEX(20), 7, 89 }, { ZAP_CLUSTER_INDEX(27), 2, 6 }, \ } // Largest attribute size is needed for various buffers @@ -1096,7 +1119,7 @@ #define ATTRIBUTE_SINGLETONS_SIZE (687) // Total size of attribute storage -#define ATTRIBUTE_MAX_SIZE (1577) +#define ATTRIBUTE_MAX_SIZE (1583) // Number of fixed endpoints #define FIXED_ENDPOINT_COUNT (3) diff --git a/zzz_generated/lighting-app/zap-generated/gen_config.h b/zzz_generated/lighting-app/zap-generated/gen_config.h index 526f5293117048..6c83cb6720bd75 100644 --- a/zzz_generated/lighting-app/zap-generated/gen_config.h +++ b/zzz_generated/lighting-app/zap-generated/gen_config.h @@ -38,6 +38,7 @@ #define EMBER_AF_FIXED_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_GROUPS_CLUSTER_SERVER_ENDPOINT_COUNT (2) #define EMBER_AF_IDENTIFY_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_LEVEL_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_LOCALIZATION_CONFIGURATION_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -107,6 +108,11 @@ #define EMBER_AF_PLUGIN_GENERAL_DIAGNOSTICS_SERVER #define EMBER_AF_PLUGIN_GENERAL_DIAGNOSTICS +// Use this macro to check if the server side of the Groups cluster is included +#define ZCL_USING_GROUPS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_GROUPS_SERVER +#define EMBER_AF_PLUGIN_GROUPS + // Use this macro to check if the server side of the Identify cluster is included #define ZCL_USING_IDENTIFY_CLUSTER_SERVER #define EMBER_AF_PLUGIN_IDENTIFY_SERVER