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 f5b0fc8dd78833..705670d1cc9d0b 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 @@ -1619,6 +1619,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, diff --git a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp index 0cede38a176352..d9a908e646123d 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/IMClusterCommandHandler.cpp @@ -1483,6 +1483,126 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En } // namespace ColorControl +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace DoorLock { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -6399,6 +6519,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC case ZCL_COLOR_CONTROL_CLUSTER_ID: clusters::ColorControl::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_DOOR_LOCK_CLUSTER_ID: clusters::DoorLock::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp b/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp index 5e6ca68ff75824..d320b277bdf2a8 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/gen/callback-stub.cpp @@ -65,6 +65,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_DESCRIPTOR_CLUSTER_ID: emberAfDescriptorClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_DOOR_LOCK_CLUSTER_ID: emberAfDoorLockClusterInitCallback(endpoint); break; @@ -236,6 +239,11 @@ void __attribute__((weak)) emberAfDescriptorClusterInitCallback(EndpointId endpo // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfDoorLockClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/all-clusters-app/all-clusters-common/gen/callback.h b/examples/all-clusters-app/all-clusters-common/gen/callback.h index 711716087de570..da4ba6521ef97b 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/callback.h +++ b/examples/all-clusters-app/all-clusters-common/gen/callback.h @@ -136,6 +136,14 @@ void emberAfContentLauncherClusterInitCallback(chip::EndpointId endpoint); */ void emberAfDescriptorClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Door Lock Cluster Init * * Cluster Init @@ -1257,6 +1265,77 @@ EmberAfStatus emberAfDescriptorClusterServerPreAttributeChangedCallback(chip::En */ void emberAfDescriptorClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Door Lock Cluster server // @@ -3847,6 +3926,13 @@ bool emberAfColorControlClusterStepSaturationCallback(chip::app::Command * comma bool emberAfColorControlClusterStopMoveStepCallback(chip::app::Command * commandObj, uint8_t optionsMask, uint8_t optionsOverride); +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief Door Lock Cluster ClearAllPins Command callback */ diff --git a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h index 3d2cfe3feb60fa..4dbd5bf891af00 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/endpoint_config.h @@ -2251,7 +2251,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 51 +#define GENERATED_CLUSTER_COUNT 52 #define GENERATED_CLUSTERS \ { \ { \ @@ -2272,6 +2272,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(28), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(29), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(29), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -2453,7 +2456,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 14, 3528 }, { ZAP_CLUSTER_INDEX(14), 35, 6187 }, { ZAP_CLUSTER_INDEX(49), 2, 8 }, \ + { ZAP_CLUSTER_INDEX(0), 15, 3528 }, { ZAP_CLUSTER_INDEX(15), 35, 6187 }, { ZAP_CLUSTER_INDEX(50), 2, 8 }, \ } // Largest attribute size is needed for various buffers @@ -2507,7 +2510,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (196) +#define EMBER_AF_GENERATED_COMMAND_COUNT (197) #define GENERATED_COMMANDS \ { \ \ @@ -2552,6 +2555,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/all-clusters-app/all-clusters-common/gen/gen_config.h b/examples/all-clusters-app/all-clusters-common/gen/gen_config.h index 033d400f93a8d1..08eb2c7cf805b7 100644 --- a/examples/all-clusters-app/all-clusters-common/gen/gen_config.h +++ b/examples/all-clusters-app/all-clusters-common/gen/gen_config.h @@ -41,6 +41,7 @@ #define EMBER_AF_COLOR_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (2) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DOOR_LOCK_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_FIXED_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -143,6 +144,11 @@ #define EMBER_AF_PLUGIN_DESCRIPTOR_SERVER #define EMBER_AF_PLUGIN_DESCRIPTOR +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Door Lock cluster is included #define ZCL_USING_DOOR_LOCK_CLUSTER_SERVER #define EMBER_AF_PLUGIN_DOOR_LOCK_SERVER diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index 885fb2862c9a50..3f9102a91a043c 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -58,6 +58,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/basic" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/bindings" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/reporting" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ias-zone-server" diff --git a/examples/bridge-app/bridge-common/bridge-app.zap b/examples/bridge-app/bridge-common/bridge-app.zap index eb012ae07c9b9e..c8694450e59d85 100644 --- a/examples/bridge-app/bridge-common/bridge-app.zap +++ b/examples/bridge-app/bridge-common/bridge-app.zap @@ -712,6 +712,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, @@ -3256,4 +3282,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp index 0c5e190e2e9f4b..71a2089917b469 100644 --- a/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp +++ b/examples/bridge-app/bridge-common/gen/IMClusterCommandHandler.cpp @@ -38,6 +38,126 @@ namespace app { namespace clusters { +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -2040,6 +2160,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/bridge-app/bridge-common/gen/callback-stub.cpp b/examples/bridge-app/bridge-common/gen/callback-stub.cpp index 3fffe9af86274f..f3c45700872ae2 100644 --- a/examples/bridge-app/bridge-common/gen/callback-stub.cpp +++ b/examples/bridge-app/bridge-common/gen/callback-stub.cpp @@ -35,6 +35,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_DESCRIPTOR_CLUSTER_ID: emberAfDescriptorClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -84,6 +87,11 @@ void __attribute__((weak)) emberAfDescriptorClusterInitCallback(EndpointId endpo // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/bridge-app/bridge-common/gen/callback.h b/examples/bridge-app/bridge-common/gen/callback.h index c48aa4ed11f309..30b89961e422d7 100644 --- a/examples/bridge-app/bridge-common/gen/callback.h +++ b/examples/bridge-app/bridge-common/gen/callback.h @@ -56,6 +56,14 @@ void emberAfBasicClusterInitCallback(chip::EndpointId endpoint); */ void emberAfDescriptorClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -283,6 +291,77 @@ EmberAfStatus emberAfDescriptorClusterServerPreAttributeChangedCallback(chip::En */ void emberAfDescriptorClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -1060,6 +1139,13 @@ void emberAfWiFiNetworkDiagnosticsClusterServerTickCallback(chip::EndpointId end // Cluster Commands Callback +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/bridge-app/bridge-common/gen/endpoint_config.h b/examples/bridge-app/bridge-common/gen/endpoint_config.h index 672ce9c811db7a..bc46dd4d75767d 100644 --- a/examples/bridge-app/bridge-common/gen/endpoint_config.h +++ b/examples/bridge-app/bridge-common/gen/endpoint_config.h @@ -909,7 +909,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 13 +#define GENERATED_CLUSTER_COUNT 14 #define GENERATED_CLUSTERS \ { \ { \ @@ -927,6 +927,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(20), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(21), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(21), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -967,7 +970,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 10, 2604 }, { ZAP_CLUSTER_INDEX(10), 3, 262 }, \ + { ZAP_CLUSTER_INDEX(0), 11, 2604 }, { ZAP_CLUSTER_INDEX(11), 3, 262 }, \ } // Largest attribute size is needed for various buffers @@ -1021,7 +1024,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (50) +#define EMBER_AF_GENERATED_COMMAND_COUNT (51) #define GENERATED_COMMANDS \ { \ \ @@ -1057,6 +1060,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/bridge-app/bridge-common/gen/gen_config.h b/examples/bridge-app/bridge-common/gen/gen_config.h index 5692c301ac1518..7e251038648187 100644 --- a/examples/bridge-app/bridge-common/gen/gen_config.h +++ b/examples/bridge-app/bridge-common/gen/gen_config.h @@ -31,6 +31,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_FIXED_LABEL_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -55,6 +56,11 @@ #define EMBER_AF_PLUGIN_DESCRIPTOR_SERVER #define EMBER_AF_PLUGIN_DESCRIPTOR +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/chip-tool/commands/clusters/Commands.h b/examples/chip-tool/commands/clusters/Commands.h index 9bc35b81a48d1b..a9063061624d97 100644 --- a/examples/chip-tool/commands/clusters/Commands.h +++ b/examples/chip-tool/commands/clusters/Commands.h @@ -1101,6 +1101,7 @@ static void OnThreadNetworkDiagnosticsActiveNetworkFaultsListListAttributeRespon | ColorControl | 0x0300 | | ContentLauncher | 0x050A | | Descriptor | 0x001D | +| DiagnosticLogs | 0x0032 | | DoorLock | 0x0101 | | EthernetNetworkDiagnostics | 0x0037 | | FixedLabel | 0x0040 | @@ -1146,6 +1147,7 @@ constexpr chip::ClusterId kBridgedDeviceBasicClusterId = 0x0039; constexpr chip::ClusterId kColorControlClusterId = 0x0300; constexpr chip::ClusterId kContentLauncherClusterId = 0x050A; constexpr chip::ClusterId kDescriptorClusterId = 0x001D; +constexpr chip::ClusterId kDiagnosticLogsClusterId = 0x0032; constexpr chip::ClusterId kDoorLockClusterId = 0x0101; constexpr chip::ClusterId kEthernetNetworkDiagnosticsClusterId = 0x0037; constexpr chip::ClusterId kFixedLabelClusterId = 0x0040; @@ -7749,6 +7751,84 @@ class ReadDescriptorClusterRevision : public ModelCommand new chip::Callback::Callback(OnDefaultFailureResponse, this); }; +/*----------------------------------------------------------------------------*\ +| Cluster DiagnosticLogs | 0x0032 | +|------------------------------------------------------------------------------| +| Commands: | | +| * RetrieveLogsRequest | 0x00 | +|------------------------------------------------------------------------------| +| Attributes: | | +\*----------------------------------------------------------------------------*/ + +/* + * Command RetrieveLogsRequest + */ +class DiagnosticLogsRetrieveLogsRequest : public ModelCommand +{ +public: + DiagnosticLogsRetrieveLogsRequest() : ModelCommand("retrieve-logs-request") + { + AddArgument("intent", 0, UINT8_MAX, &mIntent); + AddArgument("requestedProtocol", 0, UINT8_MAX, &mRequestedProtocol); + AddArgument("transferFileDesignator", &mTransferFileDesignator); + ModelCommand::AddArguments(); + } + ~DiagnosticLogsRetrieveLogsRequest() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0032) command (0x00) on endpoint %" PRIu16, endpointId); + + chip::Controller::DiagnosticLogsCluster cluster; + cluster.Associate(device, endpointId); + return cluster.RetrieveLogsRequest(onSuccessCallback->Cancel(), onFailureCallback->Cancel(), mIntent, mRequestedProtocol, + mTransferFileDesignator); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnDefaultSuccessResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); + uint8_t mIntent; + uint8_t mRequestedProtocol; + chip::ByteSpan mTransferFileDesignator; +}; + +/* + * Discover Attributes + */ +class DiscoverDiagnosticLogsAttributes : public ModelCommand +{ +public: + DiscoverDiagnosticLogsAttributes() : ModelCommand("discover") { ModelCommand::AddArguments(); } + + ~DiscoverDiagnosticLogsAttributes() + { + delete onSuccessCallback; + delete onFailureCallback; + } + + CHIP_ERROR SendCommand(ChipDevice * device, uint8_t endpointId) override + { + ChipLogProgress(chipTool, "Sending cluster (0x0000) command (0x0C) on endpoint %" PRIu16, endpointId); + + chip::Controller::DiagnosticLogsCluster cluster; + cluster.Associate(device, endpointId); + return cluster.DiscoverAttributes(onSuccessCallback->Cancel(), onFailureCallback->Cancel()); + } + +private: + chip::Callback::Callback * onSuccessCallback = + new chip::Callback::Callback(OnDefaultSuccessResponse, this); + chip::Callback::Callback * onFailureCallback = + new chip::Callback::Callback(OnDefaultFailureResponse, this); +}; + /*----------------------------------------------------------------------------*\ | Cluster DoorLock | 0x0101 | |------------------------------------------------------------------------------| @@ -21144,6 +21224,17 @@ void registerClusterDescriptor(Commands & commands) commands.Register(clusterName, clusterCommands); } +void registerClusterDiagnosticLogs(Commands & commands) +{ + const char * clusterName = "DiagnosticLogs"; + + commands_list clusterCommands = { + make_unique(), + make_unique(), + }; + + commands.Register(clusterName, clusterCommands); +} void registerClusterDoorLock(Commands & commands) { const char * clusterName = "DoorLock"; @@ -21756,6 +21847,7 @@ void registerClusters(Commands & commands) registerClusterColorControl(commands); registerClusterContentLauncher(commands); registerClusterDescriptor(commands); + registerClusterDiagnosticLogs(commands); registerClusterDoorLock(commands); registerClusterEthernetNetworkDiagnostics(commands); registerClusterFixedLabel(commands); diff --git a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp index 0c5e190e2e9f4b..71a2089917b469 100644 --- a/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lighting-app/lighting-common/gen/IMClusterCommandHandler.cpp @@ -38,6 +38,126 @@ namespace app { namespace clusters { +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -2040,6 +2160,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/lighting-app/lighting-common/gen/callback-stub.cpp b/examples/lighting-app/lighting-common/gen/callback-stub.cpp index ee9c75e7b5f912..4b9136fdfc2505 100644 --- a/examples/lighting-app/lighting-common/gen/callback-stub.cpp +++ b/examples/lighting-app/lighting-common/gen/callback-stub.cpp @@ -32,6 +32,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -73,6 +76,11 @@ void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/lighting-app/lighting-common/gen/callback.h b/examples/lighting-app/lighting-common/gen/callback.h index 58ce123ac6cffa..6ba5e10aac5c2a 100644 --- a/examples/lighting-app/lighting-common/gen/callback.h +++ b/examples/lighting-app/lighting-common/gen/callback.h @@ -48,6 +48,14 @@ void emberAfClusterInitCallback(chip::EndpointId endpoint, chip::ClusterId clust */ void emberAfBasicClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -198,6 +206,77 @@ EmberAfStatus emberAfBasicClusterServerPreAttributeChangedCallback(chip::Endpoin */ void emberAfBasicClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -906,6 +985,13 @@ void emberAfWiFiNetworkDiagnosticsClusterServerTickCallback(chip::EndpointId end // Cluster Commands Callback +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/lighting-app/lighting-common/gen/endpoint_config.h b/examples/lighting-app/lighting-common/gen/endpoint_config.h index ac387ff32d1594..c670665ec2bbcd 100644 --- a/examples/lighting-app/lighting-common/gen/endpoint_config.h +++ b/examples/lighting-app/lighting-common/gen/endpoint_config.h @@ -730,7 +730,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 11 +#define GENERATED_CLUSTER_COUNT 12 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -745,6 +745,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(15), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(16), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(16), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -782,7 +785,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 9, 1586 }, { ZAP_CLUSTER_INDEX(9), 2, 6 }, \ + { ZAP_CLUSTER_INDEX(0), 10, 1586 }, { ZAP_CLUSTER_INDEX(10), 2, 6 }, \ } // Largest attribute size is needed for various buffers @@ -836,7 +839,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (53) +#define EMBER_AF_GENERATED_COMMAND_COUNT (54) #define GENERATED_COMMANDS \ { \ \ @@ -872,6 +875,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/lighting-app/lighting-common/gen/gen_config.h b/examples/lighting-app/lighting-common/gen/gen_config.h index bc984be4a32a44..3c6ef3db042729 100644 --- a/examples/lighting-app/lighting-common/gen/gen_config.h +++ b/examples/lighting-app/lighting-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_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) @@ -48,6 +49,11 @@ #define EMBER_AF_PLUGIN_BASIC_SERVER #define EMBER_AF_PLUGIN_BASIC +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/lighting-app/lighting-common/lighting-app.zap b/examples/lighting-app/lighting-common/lighting-app.zap index 3a1b36526c5740..e888c467f186c5 100644 --- a/examples/lighting-app/lighting-common/lighting-app.zap +++ b/examples/lighting-app/lighting-common/lighting-app.zap @@ -1381,6 +1381,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, @@ -4521,4 +4547,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/lighting-app/nrfconnect/CMakeLists.txt b/examples/lighting-app/nrfconnect/CMakeLists.txt index 14e2fe43bf6af0..22198fe7c71d63 100644 --- a/examples/lighting-app/nrfconnect/CMakeLists.txt +++ b/examples/lighting-app/nrfconnect/CMakeLists.txt @@ -87,6 +87,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp + ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp ${CHIP_ROOT}/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/on-off-server/on-off-server.cpp ${CHIP_ROOT}/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp diff --git a/examples/lighting-app/telink/CMakeLists.txt b/examples/lighting-app/telink/CMakeLists.txt index 219eab853add8f..551e81d40a1a05 100644 --- a/examples/lighting-app/telink/CMakeLists.txt +++ b/examples/lighting-app/telink/CMakeLists.txt @@ -76,6 +76,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp + ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp ${CHIP_ROOT}/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/on-off-server/on-off-server.cpp ${CHIP_ROOT}/src/app/clusters/operational-credentials-server/operational-credentials-server.cpp diff --git a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp index c093d071db2483..1b4e4c97939fc6 100644 --- a/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp +++ b/examples/lock-app/lock-common/gen/IMClusterCommandHandler.cpp @@ -38,6 +38,126 @@ namespace app { namespace clusters { +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -1510,6 +1630,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/lock-app/lock-common/gen/callback-stub.cpp b/examples/lock-app/lock-common/gen/callback-stub.cpp index 58b2972d9d1531..47bcd263712239 100644 --- a/examples/lock-app/lock-common/gen/callback-stub.cpp +++ b/examples/lock-app/lock-common/gen/callback-stub.cpp @@ -32,6 +32,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -70,6 +73,11 @@ void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/lock-app/lock-common/gen/callback.h b/examples/lock-app/lock-common/gen/callback.h index 930e3d339dd6f7..fd5d8ec6147cfe 100644 --- a/examples/lock-app/lock-common/gen/callback.h +++ b/examples/lock-app/lock-common/gen/callback.h @@ -48,6 +48,14 @@ void emberAfClusterInitCallback(chip::EndpointId endpoint, chip::ClusterId clust */ void emberAfBasicClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -190,6 +198,77 @@ EmberAfStatus emberAfBasicClusterServerPreAttributeChangedCallback(chip::Endpoin */ void emberAfBasicClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -829,6 +908,13 @@ void emberAfWiFiNetworkDiagnosticsClusterServerTickCallback(chip::EndpointId end // Cluster Commands Callback +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/lock-app/lock-common/gen/endpoint_config.h b/examples/lock-app/lock-common/gen/endpoint_config.h index b98171f0ebb26b..d6ae18469869c5 100644 --- a/examples/lock-app/lock-common/gen/endpoint_config.h +++ b/examples/lock-app/lock-common/gen/endpoint_config.h @@ -723,7 +723,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 10 +#define GENERATED_CLUSTER_COUNT 11 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -738,6 +738,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(15), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(16), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(16), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -769,7 +772,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 9, 1586 }, { ZAP_CLUSTER_INDEX(9), 1, 3 }, \ + { ZAP_CLUSTER_INDEX(0), 10, 1586 }, { ZAP_CLUSTER_INDEX(10), 1, 3 }, \ } // Largest attribute size is needed for various buffers @@ -823,7 +826,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (42) +#define EMBER_AF_GENERATED_COMMAND_COUNT (43) #define GENERATED_COMMANDS \ { \ \ @@ -859,6 +862,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/lock-app/lock-common/gen/gen_config.h b/examples/lock-app/lock-common/gen/gen_config.h index ae2d5a5eaf5011..32a444f467558e 100644 --- a/examples/lock-app/lock-common/gen/gen_config.h +++ b/examples/lock-app/lock-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_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) @@ -47,6 +48,11 @@ #define EMBER_AF_PLUGIN_BASIC_SERVER #define EMBER_AF_PLUGIN_BASIC +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/lock-app/lock-common/lock-app.zap b/examples/lock-app/lock-common/lock-app.zap index 9ee6faaa939fb3..ff7464f716f413 100644 --- a/examples/lock-app/lock-common/lock-app.zap +++ b/examples/lock-app/lock-common/lock-app.zap @@ -1841,6 +1841,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, @@ -5162,4 +5188,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/lock-app/nrfconnect/CMakeLists.txt b/examples/lock-app/nrfconnect/CMakeLists.txt index 09f299aa24831d..1ed34b9267c70f 100644 --- a/examples/lock-app/nrfconnect/CMakeLists.txt +++ b/examples/lock-app/nrfconnect/CMakeLists.txt @@ -87,6 +87,7 @@ target_sources(app PRIVATE ${CHIP_ROOT}/src/app/server/StorablePeerConnection.cpp ${CHIP_ROOT}/src/app/clusters/basic/basic.cpp ${CHIP_ROOT}/src/app/clusters/bindings/bindings.cpp + ${CHIP_ROOT}/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp ${CHIP_ROOT}/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp ${CHIP_ROOT}/src/app/clusters/network-commissioning/network-commissioning-ember.cpp ${CHIP_ROOT}/src/app/clusters/network-commissioning/network-commissioning.cpp diff --git a/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp b/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp index 56046cd6f53e26..bbbb2a559cdb11 100644 --- a/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp +++ b/examples/pump-app/pump-common/gen/IMClusterCommandHandler.cpp @@ -87,6 +87,126 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En } // namespace Basic +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -2033,6 +2153,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC case ZCL_BASIC_CLUSTER_ID: clusters::Basic::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/pump-app/pump-common/gen/callback-stub.cpp b/examples/pump-app/pump-common/gen/callback-stub.cpp index d48c34727653da..139792334c93a2 100644 --- a/examples/pump-app/pump-common/gen/callback-stub.cpp +++ b/examples/pump-app/pump-common/gen/callback-stub.cpp @@ -32,6 +32,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -85,6 +88,11 @@ void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/pump-app/pump-common/gen/callback.h b/examples/pump-app/pump-common/gen/callback.h index f7492aac0e28f1..c5335e6b03822b 100644 --- a/examples/pump-app/pump-common/gen/callback.h +++ b/examples/pump-app/pump-common/gen/callback.h @@ -48,6 +48,14 @@ void emberAfClusterInitCallback(chip::EndpointId endpoint, chip::ClusterId clust */ void emberAfBasicClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -230,6 +238,77 @@ EmberAfStatus emberAfBasicClusterServerPreAttributeChangedCallback(chip::Endpoin */ void emberAfBasicClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -1442,6 +1521,13 @@ void emberAfWiFiNetworkDiagnosticsClusterServerTickCallback(chip::EndpointId end bool emberAfBasicClusterMfgSpecificPingCallback(chip::app::Command * commandObj); +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/pump-app/pump-common/gen/chip-zcl-zpro-codec-api.h b/examples/pump-app/pump-common/gen/chip-zcl-zpro-codec-api.h index ea7b53ebf36ebd..25efe373fa2ce4 100644 --- a/examples/pump-app/pump-common/gen/chip-zcl-zpro-codec-api.h +++ b/examples/pump-app/pump-common/gen/chip-zcl-zpro-codec-api.h @@ -29,6 +29,7 @@ | Cluster Name | ID | |---------------------------------------------------------------------+--------| | Basic | 0x0028 | +| DiagnosticLogs | 0x0032 | | EthernetNetworkDiagnostics | 0x0037 | | FlowMeasurement | 0x0404 | | FlowMeasurement | 0x0404 | diff --git a/examples/pump-app/pump-common/gen/encoder.cpp b/examples/pump-app/pump-common/gen/encoder.cpp index 8d5145b45ce313..33d3cc55fc3266 100644 --- a/examples/pump-app/pump-common/gen/encoder.cpp +++ b/examples/pump-app/pump-common/gen/encoder.cpp @@ -55,6 +55,7 @@ using namespace chip::Encoding::LittleEndian; | Cluster Name | ID | |---------------------------------------------------------------------+--------| | Basic | 0x0028 | +| DiagnosticLogs | 0x0032 | | EthernetNetworkDiagnostics | 0x0037 | | FlowMeasurement | 0x0404 | | FlowMeasurement | 0x0404 | diff --git a/examples/pump-app/pump-common/gen/endpoint_config.h b/examples/pump-app/pump-common/gen/endpoint_config.h index 4b2a188693207c..abaf887854064b 100644 --- a/examples/pump-app/pump-common/gen/endpoint_config.h +++ b/examples/pump-app/pump-common/gen/endpoint_config.h @@ -771,7 +771,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 18 +#define GENERATED_CLUSTER_COUNT 19 #define GENERATED_CLUSTERS \ { \ { \ @@ -800,6 +800,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(19), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(20), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(20), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -851,7 +854,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 11, 1592 }, { ZAP_CLUSTER_INDEX(11), 7, 43 }, \ + { ZAP_CLUSTER_INDEX(0), 12, 1592 }, { ZAP_CLUSTER_INDEX(12), 7, 43 }, \ } // Largest attribute size is needed for various buffers @@ -905,7 +908,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (52) +#define EMBER_AF_GENERATED_COMMAND_COUNT (53) #define GENERATED_COMMANDS \ { \ \ @@ -957,6 +960,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/pump-app/pump-common/gen/gen_config.h b/examples/pump-app/pump-common/gen/gen_config.h index f94518e0d21cae..9e8741ee02ce0b 100644 --- a/examples/pump-app/pump-common/gen/gen_config.h +++ b/examples/pump-app/pump-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_FLOW_MEASUREMENT_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_FLOW_MEASUREMENT_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -55,6 +56,11 @@ #define EMBER_AF_PLUGIN_BASIC_SERVER #define EMBER_AF_PLUGIN_BASIC +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/pump-app/pump-common/pump-app.zap b/examples/pump-app/pump-common/pump-app.zap index 524b0138b72932..60ba47863bb4fa 100644 --- a/examples/pump-app/pump-common/pump-app.zap +++ b/examples/pump-app/pump-common/pump-app.zap @@ -1308,6 +1308,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, @@ -4905,4 +4931,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp b/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp index 435332a3da6ea5..415c23704751b2 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/IMClusterCommandHandler.cpp @@ -87,6 +87,126 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En } // namespace Basic +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -1495,6 +1615,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC case ZCL_BASIC_CLUSTER_ID: clusters::Basic::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp b/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp index d48c34727653da..139792334c93a2 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/callback-stub.cpp @@ -32,6 +32,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -85,6 +88,11 @@ void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/pump-controller-app/pump-controller-common/gen/callback.h b/examples/pump-controller-app/pump-controller-common/gen/callback.h index e778b46bcdb3e2..9226d6345f2fa2 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/callback.h +++ b/examples/pump-controller-app/pump-controller-common/gen/callback.h @@ -48,6 +48,14 @@ void emberAfClusterInitCallback(chip::EndpointId endpoint, chip::ClusterId clust */ void emberAfBasicClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -230,6 +238,77 @@ EmberAfStatus emberAfBasicClusterServerPreAttributeChangedCallback(chip::Endpoin */ void emberAfBasicClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -1229,6 +1308,13 @@ void emberAfWiFiNetworkDiagnosticsClusterServerTickCallback(chip::EndpointId end bool emberAfBasicClusterMfgSpecificPingCallback(chip::app::Command * commandObj); +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/pump-controller-app/pump-controller-common/gen/chip-zcl-zpro-codec-api.h b/examples/pump-controller-app/pump-controller-common/gen/chip-zcl-zpro-codec-api.h index e37ebbad80c16e..1ccbebc7be4a6e 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/chip-zcl-zpro-codec-api.h +++ b/examples/pump-controller-app/pump-controller-common/gen/chip-zcl-zpro-codec-api.h @@ -29,6 +29,7 @@ | Cluster Name | ID | |---------------------------------------------------------------------+--------| | Basic | 0x0028 | +| DiagnosticLogs | 0x0032 | | EthernetNetworkDiagnostics | 0x0037 | | FlowMeasurement | 0x0404 | | GeneralCommissioning | 0x0030 | diff --git a/examples/pump-controller-app/pump-controller-common/gen/encoder.cpp b/examples/pump-controller-app/pump-controller-common/gen/encoder.cpp index ee642af1201860..79714e791241c2 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/encoder.cpp +++ b/examples/pump-controller-app/pump-controller-common/gen/encoder.cpp @@ -55,6 +55,7 @@ using namespace chip::Encoding::LittleEndian; | Cluster Name | ID | |---------------------------------------------------------------------+--------| | Basic | 0x0028 | +| DiagnosticLogs | 0x0032 | | EthernetNetworkDiagnostics | 0x0037 | | FlowMeasurement | 0x0404 | | GeneralCommissioning | 0x0030 | diff --git a/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h b/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h index b3828de1ab3798..33bcb831b35aba 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h +++ b/examples/pump-controller-app/pump-controller-common/gen/endpoint_config.h @@ -734,7 +734,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 15 +#define GENERATED_CLUSTER_COUNT 16 #define GENERATED_CLUSTERS \ { \ { 0x0006, ZAP_ATTRIBUTE_INDEX(0), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL }, /* Endpoint: 0, Cluster: On/off (client) */ \ @@ -753,6 +753,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(17), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(18), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(18), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -790,7 +793,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 11, 1590 }, { ZAP_CLUSTER_INDEX(11), 4, 8 }, \ + { ZAP_CLUSTER_INDEX(0), 12, 1590 }, { ZAP_CLUSTER_INDEX(12), 4, 8 }, \ } // Largest attribute size is needed for various buffers @@ -844,7 +847,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (52) +#define EMBER_AF_GENERATED_COMMAND_COUNT (53) #define GENERATED_COMMANDS \ { \ \ @@ -896,6 +899,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/pump-controller-app/pump-controller-common/gen/gen_config.h b/examples/pump-controller-app/pump-controller-common/gen/gen_config.h index f0d65bf082eaa1..99c741e458b8c9 100644 --- a/examples/pump-controller-app/pump-controller-common/gen/gen_config.h +++ b/examples/pump-controller-app/pump-controller-common/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_FLOW_MEASUREMENT_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_GENERAL_COMMISSIONING_CLUSTER_SERVER_ENDPOINT_COUNT (1) @@ -52,6 +53,11 @@ #define EMBER_AF_PLUGIN_BASIC_SERVER #define EMBER_AF_PLUGIN_BASIC +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap b/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap index 65cdc7fcaa9656..071aca92daaf55 100644 --- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap +++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.zap @@ -1308,6 +1308,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, @@ -4905,4 +4931,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp index 61170b2aefec7b..16723add433eaa 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/IMClusterCommandHandler.cpp @@ -38,6 +38,126 @@ namespace app { namespace clusters { +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -1301,6 +1421,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC SuccessOrExit(aReader.EnterContainer(dataTlvType)); switch (aClusterId) { + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp b/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp index 90ad3a1b20eaa3..5eee779386c36d 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp +++ b/examples/temperature-measurement-app/esp32/main/gen/callback-stub.cpp @@ -32,6 +32,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_BASIC_CLUSTER_ID: emberAfBasicClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -67,6 +70,11 @@ void __attribute__((weak)) emberAfBasicClusterInitCallback(EndpointId endpoint) // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/temperature-measurement-app/esp32/main/gen/callback.h b/examples/temperature-measurement-app/esp32/main/gen/callback.h index 520b39d4b0f2c8..37379312b4ad62 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/callback.h +++ b/examples/temperature-measurement-app/esp32/main/gen/callback.h @@ -48,6 +48,14 @@ void emberAfClusterInitCallback(chip::EndpointId endpoint, chip::ClusterId clust */ void emberAfBasicClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -182,6 +190,77 @@ EmberAfStatus emberAfBasicClusterServerPreAttributeChangedCallback(chip::Endpoin */ void emberAfBasicClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -753,6 +832,13 @@ void emberAfWiFiNetworkDiagnosticsClusterServerTickCallback(chip::EndpointId end // Cluster Commands Callback +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h b/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h index 9888023d26449b..a5c57b7bf25d9d 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h +++ b/examples/temperature-measurement-app/esp32/main/gen/endpoint_config.h @@ -339,7 +339,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 9 +#define GENERATED_CLUSTER_COUNT 10 #define GENERATED_CLUSTERS \ { \ { 0x0028, \ @@ -354,6 +354,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(15), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(16), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(16), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -379,7 +382,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 8, 839 }, { ZAP_CLUSTER_INDEX(8), 1, 8 }, \ + { ZAP_CLUSTER_INDEX(0), 9, 839 }, { ZAP_CLUSTER_INDEX(9), 1, 8 }, \ } // Largest attribute size is needed for various buffers @@ -433,7 +436,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (35) +#define EMBER_AF_GENERATED_COMMAND_COUNT (36) #define GENERATED_COMMANDS \ { \ \ @@ -465,6 +468,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/temperature-measurement-app/esp32/main/gen/gen_config.h b/examples/temperature-measurement-app/esp32/main/gen/gen_config.h index 36d8bd644d064a..d6debf84014402 100644 --- a/examples/temperature-measurement-app/esp32/main/gen/gen_config.h +++ b/examples/temperature-measurement-app/esp32/main/gen/gen_config.h @@ -30,6 +30,7 @@ /**** Cluster endpoint counts ****/ #define EMBER_AF_BASIC_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_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) @@ -46,6 +47,11 @@ #define EMBER_AF_PLUGIN_BASIC_SERVER #define EMBER_AF_PLUGIN_BASIC +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap b/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap index 0a386fd325c910..d8933b673c1dc3 100644 --- a/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap +++ b/examples/temperature-measurement-app/esp32/main/temperature-measurement.zap @@ -1417,6 +1417,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, diff --git a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp index 770e5a79967adb..42dcf23683fdd1 100644 --- a/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp +++ b/examples/tv-app/tv-common/gen/IMClusterCommandHandler.cpp @@ -738,6 +738,126 @@ void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, En } // namespace ContentLauncher +namespace DiagnosticLogs { + +void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, 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; + CHIP_ERROR TLVUnpackError = CHIP_NO_ERROR; + uint32_t validArgumentCount = 0; + uint32_t expectArgumentCount = 0; + uint32_t currentDecodeTagId = 0; + bool wasHandled = false; + { + switch (aCommandId) + { + case ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID: { + expectArgumentCount = 3; + uint8_t intent; + uint8_t requestedProtocol; + chip::ByteSpan transferFileDesignator; + bool argExists[3]; + + memset(argExists, 0, sizeof argExists); + + while ((TLVError = aDataTlv.Next()) == CHIP_NO_ERROR) + { + // Since call to aDataTlv.Next() is CHIP_NO_ERROR, the read head always points to an element. + // Skip this element if it is not a ContextTag, not consider it as an error if other values are valid. + if (!TLV::IsContextTag(aDataTlv.GetTag())) + { + continue; + } + currentDecodeTagId = TLV::TagNumFromTag(aDataTlv.GetTag()); + if (currentDecodeTagId < 3) + { + if (argExists[currentDecodeTagId]) + { + ChipLogProgress(Zcl, "Duplicate TLV tag %" PRIx32, TLV::TagNumFromTag(aDataTlv.GetTag())); + TLVUnpackError = CHIP_ERROR_IM_MALFORMED_COMMAND_DATA_ELEMENT; + break; + } + else + { + argExists[currentDecodeTagId] = true; + validArgumentCount++; + } + } + switch (currentDecodeTagId) + { + case 0: + TLVUnpackError = aDataTlv.Get(intent); + break; + case 1: + TLVUnpackError = aDataTlv.Get(requestedProtocol); + break; + case 2: { + const uint8_t * data = nullptr; + TLVUnpackError = aDataTlv.GetDataPtr(data); + transferFileDesignator = chip::ByteSpan(data, aDataTlv.GetLength()); + } + break; + default: + // Unsupported tag, ignore it. + ChipLogProgress(Zcl, "Unknown TLV tag during processing."); + break; + } + if (CHIP_NO_ERROR != TLVUnpackError) + { + break; + } + } + + if (CHIP_END_OF_TLV == TLVError) + { + // CHIP_END_OF_TLV means we have iterated all items in the structure, which is not a real error. + TLVError = CHIP_NO_ERROR; + } + + if (CHIP_NO_ERROR == TLVError && CHIP_NO_ERROR == TLVUnpackError && 3 == validArgumentCount) + { + // TODO(#5098) We should pass the Command Object and EndpointId to the cluster callbacks. + wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(apCommandObj, intent, requestedProtocol, + transferFileDesignator); + } + break; + } + default: { + // Unrecognized command ID, error status will apply. + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound, + Protocols::SecureChannel::Id, + Protocols::InteractionModel::ProtocolCode::UnsupportedCommand); + ChipLogError(Zcl, "Unknown command %" PRIx16 " for cluster %" PRIx16, aCommandId, ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID); + return; + } + } + } + + if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled) + { + chip::app::CommandPathParams returnStatusParam = { aEndpointId, + 0, // GroupId + ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, aCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kBadRequest, + Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand); + ChipLogProgress(Zcl, + "Failed to dispatch command, %" PRIu32 "/%" PRIu32 " arguments parsed, TLVError=%" PRIu32 + ", UnpackError=%" PRIu32 " (last decoded tag = %" PRIu32, + validArgumentCount, expectArgumentCount, TLVError, TLVUnpackError, currentDecodeTagId); + } +} + +} // namespace DiagnosticLogs + namespace GeneralCommissioning { void DispatchServerCommand(app::Command * apCommandObj, CommandId aCommandId, EndpointId aEndpointId, TLV::TLVReader & aDataTlv) @@ -3309,6 +3429,9 @@ void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aC case ZCL_CONTENT_LAUNCH_CLUSTER_ID: clusters::ContentLauncher::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); + break; case ZCL_GENERAL_COMMISSIONING_CLUSTER_ID: clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader); break; diff --git a/examples/tv-app/tv-common/gen/callback-stub.cpp b/examples/tv-app/tv-common/gen/callback-stub.cpp index 1a29aa01a1bd30..aa7450e935f217 100644 --- a/examples/tv-app/tv-common/gen/callback-stub.cpp +++ b/examples/tv-app/tv-common/gen/callback-stub.cpp @@ -53,6 +53,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_DESCRIPTOR_CLUSTER_ID: emberAfDescriptorClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_ID: emberAfEthernetNetworkDiagnosticsClusterInitCallback(endpoint); break; @@ -159,6 +162,11 @@ void __attribute__((weak)) emberAfDescriptorClusterInitCallback(EndpointId endpo // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfEthernetNetworkDiagnosticsClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/examples/tv-app/tv-common/gen/callback.h b/examples/tv-app/tv-common/gen/callback.h index 41d81e9cb8701f..e8772aefd46826 100644 --- a/examples/tv-app/tv-common/gen/callback.h +++ b/examples/tv-app/tv-common/gen/callback.h @@ -104,6 +104,14 @@ void emberAfContentLauncherClusterInitCallback(chip::EndpointId endpoint); */ void emberAfDescriptorClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Ethernet Network Diagnostics Cluster Init * * Cluster Init @@ -823,6 +831,77 @@ EmberAfStatus emberAfDescriptorClusterServerPreAttributeChangedCallback(chip::En */ void emberAfDescriptorClusterServerTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster server +// + +/** @brief Diagnostic Logs Cluster Server Init + * + * Server Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterServerInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Server Attribute Changed + * + * Server Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterServerAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Server Manufacturer Specific Attribute Changed + * + * Server Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterServerManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Server Message Sent + * + * Server Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterServerMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Server Pre Attribute Changed + * + * server Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterServerPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Server Tick + * + * server Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterServerTickCallback(chip::EndpointId endpoint); + // // Ethernet Network Diagnostics Cluster server // @@ -2281,6 +2360,13 @@ bool emberAfContentLauncherClusterLaunchContentCallback(chip::app::Command * com bool emberAfContentLauncherClusterLaunchURLCallback(chip::app::Command * commandObj, uint8_t * contentURL, uint8_t * displayString); +/** + * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback + */ + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + /** * @brief General Commissioning Cluster ArmFailSafe Command callback */ diff --git a/examples/tv-app/tv-common/gen/endpoint_config.h b/examples/tv-app/tv-common/gen/endpoint_config.h index bd0139d55d838f..e3173c619d60d5 100644 --- a/examples/tv-app/tv-common/gen/endpoint_config.h +++ b/examples/tv-app/tv-common/gen/endpoint_config.h @@ -1668,7 +1668,7 @@ }; #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 33 +#define GENERATED_CLUSTER_COUNT 34 #define GENERATED_CLUSTERS \ { \ { \ @@ -1689,6 +1689,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(27), 1, 2, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: Network Commissioning (server) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(28), 0, 0, ZAP_CLUSTER_MASK(SERVER), NULL \ + }, /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(28), 3, 258, ZAP_CLUSTER_MASK(SERVER), NULL \ }, /* Endpoint: 0, Cluster: General Diagnostics (server) */ \ @@ -1789,8 +1792,8 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 14, 3527 }, { ZAP_CLUSTER_INDEX(14), 9, 1639 }, { ZAP_CLUSTER_INDEX(23), 3, 263 }, \ - { ZAP_CLUSTER_INDEX(26), 4, 676 }, { ZAP_CLUSTER_INDEX(30), 2, 615 }, { ZAP_CLUSTER_INDEX(32), 1, 105 }, \ + { ZAP_CLUSTER_INDEX(0), 15, 3527 }, { ZAP_CLUSTER_INDEX(15), 9, 1639 }, { ZAP_CLUSTER_INDEX(24), 3, 263 }, \ + { ZAP_CLUSTER_INDEX(27), 4, 676 }, { ZAP_CLUSTER_INDEX(31), 2, 615 }, { ZAP_CLUSTER_INDEX(33), 1, 105 }, \ } // Largest attribute size is needed for various buffers @@ -1844,7 +1847,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (116) +#define EMBER_AF_GENERATED_COMMAND_COUNT (117) #define GENERATED_COMMANDS \ { \ \ @@ -1889,6 +1892,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 0, Cluster: Diagnostic Logs (server) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 0, Cluster: Software Diagnostics (server) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/examples/tv-app/tv-common/gen/gen_config.h b/examples/tv-app/tv-common/gen/gen_config.h index 2978fa01dbcea5..ae162b8a0e2e87 100644 --- a/examples/tv-app/tv-common/gen/gen_config.h +++ b/examples/tv-app/tv-common/gen/gen_config.h @@ -37,6 +37,7 @@ #define EMBER_AF_BINDING_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT (3) #define EMBER_AF_DESCRIPTOR_CLUSTER_SERVER_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_SERVER_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_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) @@ -100,6 +101,11 @@ #define EMBER_AF_PLUGIN_DESCRIPTOR_SERVER #define EMBER_AF_PLUGIN_DESCRIPTOR +// Use this macro to check if the server side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_SERVER +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS + // Use this macro to check if the server side of the Ethernet Network Diagnostics cluster is included #define ZCL_USING_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_SERVER #define EMBER_AF_PLUGIN_ETHERNET_NETWORK_DIAGNOSTICS_SERVER diff --git a/examples/tv-app/tv-common/tv-app.zap b/examples/tv-app/tv-common/tv-app.zap index 4d29cf9ca90ac6..af6bf598009ad7 100644 --- a/examples/tv-app/tv-common/tv-app.zap +++ b/examples/tv-app/tv-common/tv-app.zap @@ -1604,6 +1604,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 1, + "outgoing": 0 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 0, + "outgoing": 1 + } + ] + }, { "name": "General Diagnostics", "code": 51, @@ -8192,4 +8218,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp new file mode 100644 index 00000000000000..d8d830bfbef7f2 --- /dev/null +++ b/src/app/clusters/diagnostic-logs-server/diagnostic-logs-server.cpp @@ -0,0 +1,27 @@ +/** + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +bool emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(chip::app::Command * commandObj, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator) +{ + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + emberAfSendImmediateDefaultResponse(status); + return true; +} diff --git a/src/app/common/gen/attribute-id.h b/src/app/common/gen/attribute-id.h index c16f0051241cb4..2df8f3a473ff47 100644 --- a/src/app/common/gen/attribute-id.h +++ b/src/app/common/gen/attribute-id.h @@ -422,6 +422,12 @@ // Server attributes +// Attribute ids for cluster: Diagnostic Logs + +// Client attributes + +// Server attributes + // Attribute ids for cluster: General Diagnostics // Client attributes diff --git a/src/app/common/gen/client-command-macro.h b/src/app/common/gen/client-command-macro.h index 14082a486dbea1..489e737e228082 100644 --- a/src/app/common/gen/client-command-macro.h +++ b/src/app/common/gen/client-command-macro.h @@ -3584,6 +3584,33 @@ \ ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID, "u", timeoutMs); +/** @brief Command description for RetrieveLogsRequest + * + * Command: RetrieveLogsRequest + * @param intent LogsIntent + * @param requestedProtocol LogsTransferProtocol + * @param transferFileDesignator OCTET_STRING + */ +#define emberAfFillCommandDiagnostic \ + LogsClusterRetrieveLogsRequest(intent, requestedProtocol, transferFileDesignator) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID, "uuu", intent, requestedProtocol, transferFileDesignator); + +/** @brief Command description for RetrieveLogsResponse + * + * Command: RetrieveLogsResponse + * @param status LogsStatus + * @param content OCTET_STRING + * @param timeStamp UTC_TIME + * @param timeSinceBoot INT32U + */ +#define emberAfFillCommandDiagnostic \ + LogsClusterRetrieveLogsResponse(status, content, timeStamp, timeSinceBoot) \ + emberAfFillExternalBuffer(mask, \ + \ + ZCL_RETRIEVE_LOGS_RESPONSE_COMMAND_ID, "uuuu", status, content, timeStamp, timeSinceBoot); + /** @brief Command description for ResetWatermarks * * Command: ResetWatermarks diff --git a/src/app/common/gen/cluster-id.h b/src/app/common/gen/cluster-id.h index c94fb889d2acc7..df77d0161be0cb 100644 --- a/src/app/common/gen/cluster-id.h +++ b/src/app/common/gen/cluster-id.h @@ -100,6 +100,9 @@ static constexpr chip::ClusterId ZCL_GENERAL_COMMISSIONING_CLUSTER_ID = 0x0030; // Definitions for cluster: Network Commissioning static constexpr chip::ClusterId ZCL_NETWORK_COMMISSIONING_CLUSTER_ID = 0x0031; +// Definitions for cluster: Diagnostic Logs +static constexpr chip::ClusterId ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID = 0x0032; + // Definitions for cluster: General Diagnostics static constexpr chip::ClusterId ZCL_GENERAL_DIAGNOSTICS_CLUSTER_ID = 0x0033; diff --git a/src/app/common/gen/command-id.h b/src/app/common/gen/command-id.h index 491fd977877cda..f8a7586c68de1d 100644 --- a/src/app/common/gen/command-id.h +++ b/src/app/common/gen/command-id.h @@ -265,6 +265,10 @@ #define ZCL_DISABLE_NETWORK_RESPONSE_COMMAND_ID (0x0F) #define ZCL_GET_LAST_NETWORK_COMMISSIONING_RESULT_COMMAND_ID (0x10) +// Commands for cluster: Diagnostic Logs +#define ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID (0x00) +#define ZCL_RETRIEVE_LOGS_RESPONSE_COMMAND_ID (0x01) + // Commands for cluster: Software Diagnostics #define ZCL_RESET_WATERMARKS_COMMAND_ID (0x00) diff --git a/src/app/common/gen/enums.h b/src/app/common/gen/enums.h index 544a03bd92d71a..a3f84ef80d62eb 100644 --- a/src/app/common/gen/enums.h +++ b/src/app/common/gen/enums.h @@ -1805,6 +1805,31 @@ enum EmberAfLocationMethod : uint8_t EMBER_ZCL_LOCATION_METHOD_OUT_OF_BAND = 3, }; +// Enum for LogsIntent +enum EmberAfLogsIntent : uint8_t +{ + EMBER_ZCL_LOGS_INTENT_END_USER_SUPPORT = 0, + EMBER_ZCL_LOGS_INTENT_NETWORK_DIAG = 1, + EMBER_ZCL_LOGS_INTENT_CRASH_LOGS = 2, +}; + +// Enum for LogsStatus +enum EmberAfLogsStatus : uint8_t +{ + EMBER_ZCL_LOGS_STATUS_SUCCESS = 0, + EMBER_ZCL_LOGS_STATUS_EXHAUSTED = 1, + EMBER_ZCL_LOGS_STATUS_NO_LOGS = 2, + EMBER_ZCL_LOGS_STATUS_BUSY = 3, + EMBER_ZCL_LOGS_STATUS_DENIED = 4, +}; + +// Enum for LogsTransferProtocol +enum EmberAfLogsTransferProtocol : uint8_t +{ + EMBER_ZCL_LOGS_TRANSFER_PROTOCOL_RESPONSE_PAYLOAD = 0, + EMBER_ZCL_LOGS_TRANSFER_PROTOCOL_BDX = 1, +}; + // Enum for ManufacturerSpecificAlarmGroups enum EmberAfManufacturerSpecificAlarmGroups : uint8_t { diff --git a/src/app/common/gen/print-cluster.h b/src/app/common/gen/print-cluster.h index 0dd077c81b7b48..f507f8548ce922 100644 --- a/src/app/common/gen/print-cluster.h +++ b/src/app/common/gen/print-cluster.h @@ -180,6 +180,12 @@ #define CHIP_PRINTCLUSTER_NETWORK_COMMISSIONING_CLUSTER #endif +#if defined(ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_SERVER) || defined(ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_CLIENT) +#define CHIP_PRINTCLUSTER_DIAGNOSTIC_LOGS_CLUSTER { ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID, 50, "Diagnostic Logs" }, +#else +#define CHIP_PRINTCLUSTER_DIAGNOSTIC_LOGS_CLUSTER +#endif + #if defined(ZCL_USING_GENERAL_DIAGNOSTICS_CLUSTER_SERVER) || defined(ZCL_USING_GENERAL_DIAGNOSTICS_CLUSTER_CLIENT) #define CHIP_PRINTCLUSTER_GENERAL_DIAGNOSTICS_CLUSTER { ZCL_GENERAL_DIAGNOSTICS_CLUSTER_ID, 51, "General Diagnostics" }, #else @@ -951,6 +957,7 @@ CHIP_PRINTCLUSTER_OTA_CLIENT_CLUSTER \ CHIP_PRINTCLUSTER_GENERAL_COMMISSIONING_CLUSTER \ CHIP_PRINTCLUSTER_NETWORK_COMMISSIONING_CLUSTER \ + CHIP_PRINTCLUSTER_DIAGNOSTIC_LOGS_CLUSTER \ CHIP_PRINTCLUSTER_GENERAL_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_SOFTWARE_DIAGNOSTICS_CLUSTER \ CHIP_PRINTCLUSTER_THREAD_NETWORK_DIAGNOSTICS_CLUSTER \ diff --git a/src/app/zap-templates/zcl/diagnostic-logs-cluster.xml b/src/app/zap-templates/zcl/diagnostic-logs-cluster.xml new file mode 100644 index 00000000000000..89db19d93bfab8 --- /dev/null +++ b/src/app/zap-templates/zcl/diagnostic-logs-cluster.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + Diagnostic Logs + CHIP + The cluster provides commands for retrieving unstructured diagnostic logs from a Node that may be used to aid in diagnostics. + 0x0032 + DIAGNOSTIC_LOGS_CLUSTER + true + true + + Retrieving diagnostic logs from a Node + + + + + + Response to the RetrieveLogsRequest + + + + + + + diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 46e7509a450958..5cde9eaaacae4b 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -12,6 +12,7 @@ "switch-cluster.xml", "clusters-extensions.xml", "content-launch-cluster.xml", + "diagnostic-logs-cluster.xml", "ethernet-network-diagnostics-cluster.xml", "media-playback-cluster.xml", "low-power-cluster.xml", diff --git a/src/app/zap_cluster_list.py b/src/app/zap_cluster_list.py index 08bee9d8ed8412..be6bdb079c04ab 100755 --- a/src/app/zap_cluster_list.py +++ b/src/app/zap_cluster_list.py @@ -24,6 +24,7 @@ 'CONTENT_LAUNCH_CLUSTER': ['content-launch-server'], 'DESCRIPTOR_CLUSTER': ['descriptor'], 'DEVICE_TEMP_CLUSTER': [], + 'DIAGNOSTIC_LOGS_CLUSTER': ['diagnostic-logs-server'], 'DOOR_LOCK_CLUSTER': ['door-lock-server'], 'ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER': [], 'FIXED_LABEL_CLUSTER': [], @@ -82,6 +83,7 @@ 'CONTENT_LAUNCH_CLUSTER': [], 'DEVICE_TEMP_CLUSTER': [], 'DESCRIPTOR_CLUSTER': [], + 'DIAGNOSTIC_LOGS_CLUSTER': [], 'DOOR_LOCK_CLUSTER': [], 'ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER': [], 'FIXED_LABEL_CLUSTER': [], diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index a07bad1c8ec905..b061035f44a073 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -1791,6 +1791,32 @@ } ] }, + { + "name": "Diagnostic Logs", + "code": 50, + "mfgCode": null, + "define": "DIAGNOSTIC_LOGS_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "RetrieveLogsRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "incoming": 0, + "outgoing": 1 + }, + { + "name": "RetrieveLogsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "incoming": 1, + "outgoing": 0 + } + ] + }, { "name": "General Diagnostics", "code": 51, diff --git a/src/controller/data_model/gen/CHIPClusters.cpp b/src/controller/data_model/gen/CHIPClusters.cpp index 72a09dbfd979b7..c13bb7329902e4 100644 --- a/src/controller/data_model/gen/CHIPClusters.cpp +++ b/src/controller/data_model/gen/CHIPClusters.cpp @@ -2564,6 +2564,62 @@ CHIP_ERROR DescriptorCluster::ReadAttributeClusterRevision(Callback::Cancelable return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); } +// DiagnosticLogs Cluster Commands +CHIP_ERROR DiagnosticLogsCluster::RetrieveLogsRequest(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback, uint8_t intent, + uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + app::CommandSender * sender = nullptr; + TLV::TLVWriter * writer = nullptr; + uint8_t argSeqNumber = 0; + + // Used when encoding non-empty command. Suppress error message when encoding empty commands. + (void) writer; + (void) argSeqNumber; + + VerifyOrReturnError(mDevice != nullptr, CHIP_ERROR_INCORRECT_STATE); + + app::CommandPathParams cmdParams = { mEndpoint, /* group id */ 0, mClusterId, kRetrieveLogsRequestCommandId, + (chip::app::CommandPathFlags::kEndpointIdValid) }; + + SuccessOrExit(err = chip::app::InteractionModelEngine::GetInstance()->NewCommandSender(&sender)); + + SuccessOrExit(err = sender->PrepareCommand(cmdParams)); + + VerifyOrExit((writer = sender->GetCommandDataElementTLVWriter()) != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + // intent: logsIntent + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), intent)); + // requestedProtocol: logsTransferProtocol + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), requestedProtocol)); + // transferFileDesignator: octetString + SuccessOrExit(err = writer->Put(TLV::ContextTag(argSeqNumber++), transferFileDesignator)); + + SuccessOrExit(err = sender->FinishCommand()); + + // #6308: This is a temporary solution before we fully support IM on application side and should be replaced by IMDelegate. + mDevice->AddIMResponseHandler(sender, onSuccessCallback, onFailureCallback); + + err = mDevice->SendCommands(sender); + +exit: + // On error, we are responsible to close the sender. + if (err != CHIP_NO_ERROR && sender != nullptr) + { + sender->Shutdown(); + } + return err; +} + +// DiagnosticLogs Cluster Attributes +CHIP_ERROR DiagnosticLogsCluster::DiscoverAttributes(Callback::Cancelable * onSuccessCallback, + Callback::Cancelable * onFailureCallback) +{ + uint8_t seqNum = mDevice->GetNextSequenceNumber(); + System::PacketBufferHandle encodedCommand = encodeDiagnosticLogsClusterDiscoverAttributes(seqNum, mEndpoint); + return SendCommand(seqNum, std::move(encodedCommand), onSuccessCallback, onFailureCallback); +} + // DoorLock Cluster Commands CHIP_ERROR DoorLockCluster::ClearAllPins(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback) { diff --git a/src/controller/data_model/gen/CHIPClusters.h b/src/controller/data_model/gen/CHIPClusters.h index 994dc8148949be..ad0dc2cd5650d2 100644 --- a/src/controller/data_model/gen/CHIPClusters.h +++ b/src/controller/data_model/gen/CHIPClusters.h @@ -39,6 +39,7 @@ constexpr ClusterId kBridgedDeviceBasicClusterId = 0x0039; constexpr ClusterId kColorControlClusterId = 0x0300; constexpr ClusterId kContentLauncherClusterId = 0x050A; constexpr ClusterId kDescriptorClusterId = 0x001D; +constexpr ClusterId kDiagnosticLogsClusterId = 0x0032; constexpr ClusterId kDoorLockClusterId = 0x0101; constexpr ClusterId kEthernetNetworkDiagnosticsClusterId = 0x0037; constexpr ClusterId kFixedLabelClusterId = 0x0040; @@ -499,6 +500,23 @@ class DLL_EXPORT DescriptorCluster : public ClusterBase CHIP_ERROR ReadAttributeClusterRevision(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); }; +class DLL_EXPORT DiagnosticLogsCluster : public ClusterBase +{ +public: + DiagnosticLogsCluster() : ClusterBase(kDiagnosticLogsClusterId) {} + ~DiagnosticLogsCluster() {} + + // Cluster Commands + CHIP_ERROR RetrieveLogsRequest(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback, + uint8_t intent, uint8_t requestedProtocol, chip::ByteSpan transferFileDesignator); + + // Cluster Attributes + CHIP_ERROR DiscoverAttributes(Callback::Cancelable * onSuccessCallback, Callback::Cancelable * onFailureCallback); + +private: + static constexpr CommandId kRetrieveLogsRequestCommandId = 0x00; +}; + class DLL_EXPORT DoorLockCluster : public ClusterBase { public: diff --git a/src/controller/data_model/gen/callback-stub.cpp b/src/controller/data_model/gen/callback-stub.cpp index 059ae7e0761f39..8c996fead7c2af 100644 --- a/src/controller/data_model/gen/callback-stub.cpp +++ b/src/controller/data_model/gen/callback-stub.cpp @@ -65,6 +65,9 @@ void emberAfClusterInitCallback(EndpointId endpoint, ClusterId clusterId) case ZCL_DESCRIPTOR_CLUSTER_ID: emberAfDescriptorClusterInitCallback(endpoint); break; + case ZCL_DIAGNOSTIC_LOGS_CLUSTER_ID: + emberAfDiagnosticLogsClusterInitCallback(endpoint); + break; case ZCL_DOOR_LOCK_CLUSTER_ID: emberAfDoorLockClusterInitCallback(endpoint); break; @@ -224,6 +227,11 @@ void __attribute__((weak)) emberAfDescriptorClusterInitCallback(EndpointId endpo // To prevent warning (void) endpoint; } +void __attribute__((weak)) emberAfDiagnosticLogsClusterInitCallback(EndpointId endpoint) +{ + // To prevent warning + (void) endpoint; +} void __attribute__((weak)) emberAfDoorLockClusterInitCallback(EndpointId endpoint) { // To prevent warning diff --git a/src/controller/data_model/gen/callback.h b/src/controller/data_model/gen/callback.h index 10c15cb1c274ea..ead6b8a597e530 100644 --- a/src/controller/data_model/gen/callback.h +++ b/src/controller/data_model/gen/callback.h @@ -136,6 +136,14 @@ void emberAfContentLauncherClusterInitCallback(chip::EndpointId endpoint); */ void emberAfDescriptorClusterInitCallback(chip::EndpointId endpoint); +/** @brief Diagnostic Logs Cluster Init + * + * Cluster Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint); + /** @brief Door Lock Cluster Init * * Cluster Init @@ -1225,6 +1233,77 @@ EmberAfStatus emberAfDescriptorClusterClientPreAttributeChangedCallback(chip::En */ void emberAfDescriptorClusterClientTickCallback(chip::EndpointId endpoint); +// +// Diagnostic Logs Cluster client +// + +/** @brief Diagnostic Logs Cluster Client Init + * + * Client Init + * + * @param endpoint Endpoint that is being initialized + */ +void emberAfDiagnosticLogsClusterClientInitCallback(chip::EndpointId endpoint); + +/** @brief Diagnostic Logs Cluster Client Attribute Changed + * + * Client Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + */ +void emberAfDiagnosticLogsClusterClientAttributeChangedCallback(chip::EndpointId endpoint, chip::AttributeId attributeId); + +/** @brief Diagnostic Logs Cluster Client Manufacturer Specific Attribute Changed + * + * Client Manufacturer Specific Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute that changed + * @param manufacturerCode Manufacturer Code of the attribute that changed + */ +void emberAfDiagnosticLogsClusterClientManufacturerSpecificAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + uint16_t manufacturerCode); + +/** @brief Diagnostic Logs Cluster Client Message Sent + * + * Client Message Sent + * + * @param type The type of message sent + * @param destination The destination to which the message was sent + * @param apsFrame The APS frame for the message + * @param msgLen The length of the message + * @param message The message that was sent + * @param status The status of the sent message + */ +void emberAfDiagnosticLogsClusterClientMessageSentCallback(const chip::MessageSendDestination & destination, + EmberApsFrame * apsFrame, uint16_t msgLen, uint8_t * message, + EmberStatus status); + +/** @brief Diagnostic Logs Cluster Client Pre Attribute Changed + * + * client Pre Attribute Changed + * + * @param endpoint Endpoint that is being initialized + * @param attributeId Attribute to be changed + * @param attributeType Attribute type + * @param size Attribute size + * @param value Attribute value + */ +EmberAfStatus emberAfDiagnosticLogsClusterClientPreAttributeChangedCallback(chip::EndpointId endpoint, + chip::AttributeId attributeId, + EmberAfAttributeType attributeType, uint16_t size, + uint8_t * value); + +/** @brief Diagnostic Logs Cluster Client Tick + * + * client Tick + * + * @param endpoint Endpoint that is being served + */ +void emberAfDiagnosticLogsClusterClientTickCallback(chip::EndpointId endpoint); + // // Door Lock Cluster client // diff --git a/src/controller/data_model/gen/chip-zcl-zpro-codec-api.h b/src/controller/data_model/gen/chip-zcl-zpro-codec-api.h index 968f0e81c1c072..9520dd654bc8ed 100644 --- a/src/controller/data_model/gen/chip-zcl-zpro-codec-api.h +++ b/src/controller/data_model/gen/chip-zcl-zpro-codec-api.h @@ -40,6 +40,7 @@ | ColorControl | 0x0300 | | ContentLauncher | 0x050A | | Descriptor | 0x001D | +| DiagnosticLogs | 0x0032 | | DoorLock | 0x0101 | | EthernetNetworkDiagnostics | 0x0037 | | FixedLabel | 0x0040 | @@ -1401,6 +1402,22 @@ chip::System::PacketBufferHandle encodeDescriptorClusterReadPartsListAttribute(u chip::System::PacketBufferHandle encodeDescriptorClusterReadClusterRevisionAttribute(uint8_t seqNum, chip::EndpointId destinationEndpoint); +/*----------------------------------------------------------------------------*\ +| Cluster DiagnosticLogs | 0x0032 | +|------------------------------------------------------------------------------| +| Commands: | | +| * RetrieveLogsRequest | 0x00 | +|------------------------------------------------------------------------------| +| Attributes: | | +\*----------------------------------------------------------------------------*/ + +/** + * @brief + * Encode a Diagnostic Logs server discover command into buffer including the APS frame + */ +chip::System::PacketBufferHandle encodeDiagnosticLogsClusterDiscoverAttributes(uint8_t seqNum, + chip::EndpointId destinationEndpoint); + /*----------------------------------------------------------------------------*\ | Cluster DoorLock | 0x0101 | |------------------------------------------------------------------------------| diff --git a/src/controller/data_model/gen/encoder.cpp b/src/controller/data_model/gen/encoder.cpp index c4080b529369ce..9bfb18b4a1bbfc 100644 --- a/src/controller/data_model/gen/encoder.cpp +++ b/src/controller/data_model/gen/encoder.cpp @@ -66,6 +66,7 @@ using namespace chip::Encoding::LittleEndian; | ColorControl | 0x0300 | | ContentLauncher | 0x050A | | Descriptor | 0x001D | +| DiagnosticLogs | 0x0032 | | DoorLock | 0x0101 | | EthernetNetworkDiagnostics | 0x0037 | | FixedLabel | 0x0040 | @@ -176,6 +177,9 @@ using namespace chip::Encoding::LittleEndian; #define DESCRIPTOR_CLUSTER_ID 0x001D +#define DIAGNOSTIC_LOGS_CLUSTER_ID 0x0032 +#define ZCL_RETRIEVE_LOGS_REQUEST_COMMAND_ID (0x00) + #define DOOR_LOCK_CLUSTER_ID 0x0101 #define ZCL_CLEAR_ALL_PINS_COMMAND_ID (0x08) #define ZCL_CLEAR_ALL_RFIDS_COMMAND_ID (0x19) @@ -2231,6 +2235,22 @@ PacketBufferHandle encodeDescriptorClusterReadClusterRevisionAttribute(uint8_t s COMMAND_FOOTER(); } +/*----------------------------------------------------------------------------*\ +| Cluster DiagnosticLogs | 0x0032 | +|------------------------------------------------------------------------------| +| Commands: | | +| * RetrieveLogsRequest | 0x00 | +|------------------------------------------------------------------------------| +| Attributes: | | +\*----------------------------------------------------------------------------*/ + +PacketBufferHandle encodeDiagnosticLogsClusterDiscoverAttributes(uint8_t seqNum, EndpointId destinationEndpoint) +{ + COMMAND_HEADER("DiscoverDiagnosticLogsAttributes", DIAGNOSTIC_LOGS_CLUSTER_ID); + buf.Put8(kFrameControlGlobalCommand).Put8(seqNum).Put8(ZCL_DISCOVER_ATTRIBUTES_COMMAND_ID).Put16(0x0000).Put8(0xFF); + COMMAND_FOOTER(); +} + /*----------------------------------------------------------------------------*\ | Cluster DoorLock | 0x0101 | |------------------------------------------------------------------------------| diff --git a/src/controller/data_model/gen/endpoint_config.h b/src/controller/data_model/gen/endpoint_config.h index d79a94e4b0707e..8a1bbbaf9820ca 100644 --- a/src/controller/data_model/gen/endpoint_config.h +++ b/src/controller/data_model/gen/endpoint_config.h @@ -206,7 +206,7 @@ #define GENERATED_FUNCTION_ARRAYS #define ZAP_CLUSTER_MASK(mask) CLUSTER_MASK_##mask -#define GENERATED_CLUSTER_COUNT 43 +#define GENERATED_CLUSTER_COUNT 44 #define GENERATED_CLUSTERS \ { \ { 0x0003, ZAP_ATTRIBUTE_INDEX(0), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL }, /* Endpoint: 1, Cluster: Identify (client) */ \ @@ -232,6 +232,9 @@ { \ 0x0031, ZAP_ATTRIBUTE_INDEX(10), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: Network Commissioning (client) */ \ + { \ + 0x0032, ZAP_ATTRIBUTE_INDEX(11), 0, 0, ZAP_CLUSTER_MASK(CLIENT), NULL \ + }, /* Endpoint: 1, Cluster: Diagnostic Logs (client) */ \ { \ 0x0033, ZAP_ATTRIBUTE_INDEX(11), 1, 2, ZAP_CLUSTER_MASK(CLIENT), NULL \ }, /* Endpoint: 1, Cluster: General Diagnostics (client) */ \ @@ -333,7 +336,7 @@ // This is an array of EmberAfEndpointType structures. #define GENERATED_ENDPOINT_TYPES \ { \ - { ZAP_CLUSTER_INDEX(0), 43, 86 }, \ + { ZAP_CLUSTER_INDEX(0), 44, 86 }, \ } // Largest attribute size is needed for various buffers @@ -387,7 +390,7 @@ // Array of EmberAfCommandMetadata structs. #define ZAP_COMMAND_MASK(mask) COMMAND_MASK_##mask -#define EMBER_AF_GENERATED_COMMAND_COUNT (219) +#define EMBER_AF_GENERATED_COMMAND_COUNT (220) #define GENERATED_COMMANDS \ { \ \ @@ -479,6 +482,9 @@ { 0x0031, 0x0F, ZAP_COMMAND_MASK(INCOMING_CLIENT) }, /* DisableNetworkResponse */ \ { 0x0031, 0x10, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* GetLastNetworkCommissioningResult */ \ \ + /* Endpoint: 1, Cluster: Diagnostic Logs (client) */ \ + { 0x0032, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* RetrieveLogsRequest */ \ + \ /* Endpoint: 1, Cluster: Software Diagnostics (client) */ \ { 0x0034, 0x00, ZAP_COMMAND_MASK(INCOMING_SERVER) }, /* ResetWatermarks */ \ \ diff --git a/src/controller/data_model/gen/gen_config.h b/src/controller/data_model/gen/gen_config.h index 7293f3889bbd4a..4e44cdee743abd 100644 --- a/src/controller/data_model/gen/gen_config.h +++ b/src/controller/data_model/gen/gen_config.h @@ -41,6 +41,7 @@ #define EMBER_AF_COLOR_CONTROL_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_CONTENT_LAUNCH_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_DESCRIPTOR_CLUSTER_CLIENT_ENDPOINT_COUNT (1) +#define EMBER_AF_DIAGNOSTIC_LOGS_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_DOOR_LOCK_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_ETHERNET_NETWORK_DIAGNOSTICS_CLUSTER_CLIENT_ENDPOINT_COUNT (1) #define EMBER_AF_FIXED_LABEL_CLUSTER_CLIENT_ENDPOINT_COUNT (1) @@ -123,6 +124,10 @@ #define ZCL_USING_DESCRIPTOR_CLUSTER_CLIENT #define EMBER_AF_PLUGIN_DESCRIPTOR_CLIENT +// Use this macro to check if the client side of the Diagnostic Logs cluster is included +#define ZCL_USING_DIAGNOSTIC_LOGS_CLUSTER_CLIENT +#define EMBER_AF_PLUGIN_DIAGNOSTIC_LOGS_CLIENT + // Use this macro to check if the client side of the Door Lock cluster is included #define ZCL_USING_DOOR_LOCK_CLUSTER_CLIENT #define EMBER_AF_PLUGIN_DOOR_LOCK_CLIENT diff --git a/src/controller/java/gen/CHIPClusters-JNI.cpp b/src/controller/java/gen/CHIPClusters-JNI.cpp index 1535366159c755..e1890e18791aad 100644 --- a/src/controller/java/gen/CHIPClusters-JNI.cpp +++ b/src/controller/java/gen/CHIPClusters-JNI.cpp @@ -6504,6 +6504,65 @@ JNI_METHOD(jlong, DescriptorCluster, initWithDevice)(JNIEnv * env, jobject self, return reinterpret_cast(cppCluster); } +JNI_METHOD(jlong, DiagnosticLogsCluster, initWithDevice)(JNIEnv * env, jobject self, jlong devicePtr, jint endpointId) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + DiagnosticLogsCluster * cppCluster = new DiagnosticLogsCluster(); + + cppCluster->Associate(reinterpret_cast(devicePtr), endpointId); + return reinterpret_cast(cppCluster); +} + +JNI_METHOD(void, DiagnosticLogsCluster, retrieveLogsRequest) +(JNIEnv * env, jobject self, jlong clusterPtr, jobject callback, jint intent, jint requestedProtocol, + jbyteArray transferFileDesignator) +{ + StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); + CHIP_ERROR err = CHIP_NO_ERROR; + DiagnosticLogsCluster * cppCluster; + + JniByteArray transferFileDesignatorArr(env, transferFileDesignator); + CHIPDefaultSuccessCallback * onSuccess; + CHIPDefaultFailureCallback * onFailure; + + cppCluster = reinterpret_cast(clusterPtr); + VerifyOrExit(cppCluster != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + onSuccess = new CHIPDefaultSuccessCallback(callback); + VerifyOrExit(onSuccess != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + onFailure = new CHIPDefaultFailureCallback(callback); + VerifyOrExit(onFailure != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + + err = cppCluster->RetrieveLogsRequest( + onSuccess->Cancel(), onFailure->Cancel(), intent, requestedProtocol, + chip::ByteSpan((const uint8_t *) transferFileDesignatorArr.data(), transferFileDesignatorArr.size())); + SuccessOrExit(err); + +exit: + if (err != CHIP_NO_ERROR) + { + delete onSuccess; + delete onFailure; + + jthrowable exception; + jmethodID method; + + err = JniReferences::GetInstance().FindMethod(env, callback, "onError", "(Ljava/lang/Exception;)V", &method); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %d", err); + return; + } + + err = CreateIllegalStateException(env, "Error invoking cluster", err, exception); + if (err != CHIP_NO_ERROR) + { + ChipLogError(Zcl, "Error throwing IllegalStateException %d", err); + return; + } + env->CallVoidMethod(callback, method, exception); + } +} JNI_METHOD(jlong, DoorLockCluster, initWithDevice)(JNIEnv * env, jobject self, jlong devicePtr, jint endpointId) { StackLockGuard lock(JniReferences::GetInstance().GetStackLock()); diff --git a/src/controller/java/gen/ChipClusters.java b/src/controller/java/gen/ChipClusters.java index 1f69c557fcb68c..2642d664cc0a31 100644 --- a/src/controller/java/gen/ChipClusters.java +++ b/src/controller/java/gen/ChipClusters.java @@ -588,6 +588,31 @@ public DescriptorCluster(long devicePtr, int endpointId) { public native long initWithDevice(long devicePtr, int endpointId); } + public static class DiagnosticLogsCluster extends BaseChipCluster { + public DiagnosticLogsCluster(long devicePtr, int endpointId) { + super(devicePtr, endpointId); + } + + @Override + public native long initWithDevice(long devicePtr, int endpointId); + + public void retrieveLogsRequest( + DefaultClusterCallback callback, + int intent, + int requestedProtocol, + byte[] transferFileDesignator) { + retrieveLogsRequest( + chipClusterPtr, callback, intent, requestedProtocol, transferFileDesignator); + } + + private native void retrieveLogsRequest( + long chipClusterPtr, + DefaultClusterCallback callback, + int intent, + int requestedProtocol, + byte[] transferFileDesignator); + } + public static class DoorLockCluster extends BaseChipCluster { public DoorLockCluster(long devicePtr, int endpointId) { super(devicePtr, endpointId); diff --git a/src/controller/python/chip/clusters/CHIPClusters.cpp b/src/controller/python/chip/clusters/CHIPClusters.cpp index d8f56c277090e9..fea3b5a61fa1b2 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.cpp +++ b/src/controller/python/chip/clusters/CHIPClusters.cpp @@ -1870,6 +1870,22 @@ CHIP_ERROR chip_ime_ReadAttribute_Descriptor_ClusterRevision(chip::Controller::D } // End of Cluster Descriptor +// Cluster DiagnosticLogs + +CHIP_ERROR chip_ime_AppendCommand_DiagnosticLogs_RetrieveLogsRequest(chip::Controller::Device * device, + chip::EndpointId ZCLendpointId, chip::GroupId, uint8_t intent, + uint8_t requestedProtocol, + const uint8_t * transferFileDesignator, + uint32_t transferFileDesignator_Len) +{ + VerifyOrReturnError(device != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + chip::Controller::DiagnosticLogsCluster cluster; + cluster.Associate(device, ZCLendpointId); + return cluster.RetrieveLogsRequest(nullptr, nullptr, intent, requestedProtocol, + chip::ByteSpan(transferFileDesignator, transferFileDesignator_Len)); +} + +// End of Cluster DiagnosticLogs // Cluster DoorLock CHIP_ERROR chip_ime_AppendCommand_DoorLock_ClearAllPins(chip::Controller::Device * device, chip::EndpointId ZCLendpointId, diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index 10c971e7eb35b6..1f2562195f87f0 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -204,6 +204,13 @@ def ListClusterCommands(self): }, "Descriptor": { }, + "DiagnosticLogs": { + "RetrieveLogsRequest": { + "intent": "int", + "requestedProtocol": "int", + "transferFileDesignator": "bytes", + }, + }, "DoorLock": { "ClearAllPins": { }, @@ -1186,6 +1193,8 @@ def ListClusterAttributes(self): "type": "int", }, }, + "DiagnosticLogs": { + }, "DoorLock": { "LockState": { "attributeId": 0x0000, @@ -2165,6 +2174,10 @@ def ClusterContentLauncher_CommandLaunchURL(self, device: ctypes.c_void_p, ZCLen return self._chipLib.chip_ime_AppendCommand_ContentLauncher_LaunchURL( device, ZCLendpoint, ZCLgroupid, contentURL, len(contentURL), displayString, len(displayString) ) + def ClusterDiagnosticLogs_CommandRetrieveLogsRequest(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int, intent: int, requestedProtocol: int, transferFileDesignator: bytes): + return self._chipLib.chip_ime_AppendCommand_DiagnosticLogs_RetrieveLogsRequest( + device, ZCLendpoint, ZCLgroupid, intent, requestedProtocol, transferFileDesignator, len(transferFileDesignator) + ) def ClusterDoorLock_CommandClearAllPins(self, device: ctypes.c_void_p, ZCLendpoint: int, ZCLgroupid: int): return self._chipLib.chip_ime_AppendCommand_DoorLock_ClearAllPins( device, ZCLendpoint, ZCLgroupid @@ -3892,6 +3905,10 @@ def InitLib(self, chipLib): # Cluster Descriptor ReadAttribute ClusterRevision self._chipLib.chip_ime_ReadAttribute_Descriptor_ClusterRevision.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16] self._chipLib.chip_ime_ReadAttribute_Descriptor_ClusterRevision.restype = ctypes.c_uint32 + # Cluster DiagnosticLogs + # Cluster DiagnosticLogs Command RetrieveLogsRequest + self._chipLib.chip_ime_AppendCommand_DiagnosticLogs_RetrieveLogsRequest.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint8, ctypes.c_uint8, ctypes.c_char_p, ctypes.c_uint32] + self._chipLib.chip_ime_AppendCommand_DiagnosticLogs_RetrieveLogsRequest.restype = ctypes.c_uint32 # Cluster DoorLock # Cluster DoorLock Command ClearAllPins self._chipLib.chip_ime_AppendCommand_DoorLock_ClearAllPins.argtypes = [ctypes.c_void_p, ctypes.c_uint8, ctypes.c_uint16] diff --git a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h index 74d3f0c743b87c..27d0bc5cb6b651 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h +++ b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.h @@ -428,6 +428,19 @@ NS_ASSUME_NONNULL_BEGIN @end +/** + * Cluster Diagnostic Logs + * + */ +@interface CHIPDiagnosticLogs : CHIPCluster + +- (void)retrieveLogsRequest:(uint8_t)intent + requestedProtocol:(uint8_t)requestedProtocol + transferFileDesignator:(NSData *)transferFileDesignator + responseHandler:(ResponseHandler)responseHandler; + +@end + /** * Cluster Door Lock * diff --git a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm index f72bcabb602136..39f17409c33f17 100644 --- a/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm +++ b/src/darwin/Framework/CHIP/gen/CHIPClustersObjc.mm @@ -8637,6 +8637,50 @@ - (void)readAttributeClusterRevisionWithResponseHandler:(ResponseHandler)respons @end +@interface CHIPDiagnosticLogs () +@property (readonly) Controller::DiagnosticLogsCluster cppCluster; +@end + +@implementation CHIPDiagnosticLogs + +- (Controller::ClusterBase *)getCluster +{ + return &_cppCluster; +} + +- (void)retrieveLogsRequest:(uint8_t)intent + requestedProtocol:(uint8_t)requestedProtocol + transferFileDesignator:(NSData *)transferFileDesignator + responseHandler:(ResponseHandler)responseHandler +{ + CHIPDefaultSuccessCallbackBridge * onSuccess = new CHIPDefaultSuccessCallbackBridge(responseHandler, [self callbackQueue]); + if (!onSuccess) { + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + CHIPDefaultFailureCallbackBridge * onFailure = new CHIPDefaultFailureCallbackBridge(responseHandler, [self callbackQueue]); + if (!onFailure) { + delete onSuccess; + responseHandler([CHIPError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil); + return; + } + + __block CHIP_ERROR err; + dispatch_sync([self chipWorkQueue], ^{ + err = self.cppCluster.RetrieveLogsRequest(onSuccess->Cancel(), onFailure->Cancel(), intent, requestedProtocol, + chip::ByteSpan((const uint8_t *) transferFileDesignator.bytes, transferFileDesignator.length)); + }); + + if (err != CHIP_NO_ERROR) { + delete onSuccess; + delete onFailure; + responseHandler([CHIPError errorForCHIPErrorCode:err], nil); + } +} + +@end + @interface CHIPDoorLock () @property (readonly) Controller::DoorLockCluster cppCluster; @end