text: /*
   *
   *    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.
   */
  
  // THIS FILE IS GENERATED BY ZAP
  
  #include <cinttypes>
  #include <cstdint>
  
  #include "app/common/gen/af-structs.h"
  #include "app/common/gen/callback.h"
  #include "app/common/gen/ids/Clusters.h"
  #include "app/common/gen/ids/Commands.h"
  #include "app/util/util.h"
  
  #include <app/InteractionModelEngine.h>
  
  // Currently we need some work to keep compatible with ember lib.
  #include <app/util/ember-compatibility-functions.h>
  
  namespace chip {
  namespace app {
  
  // Cluster specific command parsing
  
  namespace clusters {
  
  namespace DiagnosticLogs {
  
  void DispatchServerCommand(app::CommandHandler * 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 Clusters::DiagnosticLogs::Commands::Ids::RetrieveLogsRequest: {
              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)
              {
                  wasHandled = emberAfDiagnosticLogsClusterRetrieveLogsRequestCallback(aEndpointId, apCommandObj, intent,
                                                                                       requestedProtocol, transferFileDesignator);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 Clusters::DiagnosticLogs::Id, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id,
                                          Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
              ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, Clusters::DiagnosticLogs::Id);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             Clusters::DiagnosticLogs::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=%" CHIP_ERROR_FORMAT
                          ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError),
                          ChipError::FormatError(TLVUnpackError), currentDecodeTagId);
          // A command with no arguments would never write currentDecodeTagId.  If
          // progress logging is also disabled, it would look unused.  Silence that
          // warning.
          UNUSED_VAR(currentDecodeTagId);
      }
  }
  
  } // namespace DiagnosticLogs
  
  namespace GeneralCommissioning {
  
  void DispatchServerCommand(app::CommandHandler * 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 Clusters::GeneralCommissioning::Commands::Ids::ArmFailSafe: {
              expectArgumentCount = 3;
              uint16_t expiryLengthSeconds;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              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(expiryLengthSeconds);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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)
              {
                  wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback(aEndpointId, apCommandObj, expiryLengthSeconds,
                                                                                     breadcrumb, timeoutMs);
              }
              break;
          }
          case Clusters::GeneralCommissioning::Commands::Ids::CommissioningComplete: {
  
              wasHandled = emberAfGeneralCommissioningClusterCommissioningCompleteCallback(aEndpointId, apCommandObj);
              break;
          }
          case Clusters::GeneralCommissioning::Commands::Ids::SetRegulatoryConfig: {
              expectArgumentCount = 4;
              uint8_t location;
              const uint8_t * countryCode;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              bool argExists[4];
  
              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 < 4)
                  {
                      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(location);
                      break;
                  case 1:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(countryCode);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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 && 4 == validArgumentCount)
              {
                  wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(
                      aEndpointId, apCommandObj, location, const_cast<uint8_t *>(countryCode), breadcrumb, timeoutMs);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 Clusters::GeneralCommissioning::Id, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id,
                                          Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
              ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, Clusters::GeneralCommissioning::Id);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             Clusters::GeneralCommissioning::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=%" CHIP_ERROR_FORMAT
                          ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError),
                          ChipError::FormatError(TLVUnpackError), currentDecodeTagId);
          // A command with no arguments would never write currentDecodeTagId.  If
          // progress logging is also disabled, it would look unused.  Silence that
          // warning.
          UNUSED_VAR(currentDecodeTagId);
      }
  }
  
  } // namespace GeneralCommissioning
  
  namespace NetworkCommissioning {
  
  void DispatchServerCommand(app::CommandHandler * 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 Clusters::NetworkCommissioning::Commands::Ids::AddWiFiNetwork: {
              expectArgumentCount = 4;
              chip::ByteSpan ssid;
              chip::ByteSpan credentials;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              bool argExists[4];
  
              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 < 4)
                  {
                      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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      ssid                 = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      credentials          = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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 && 4 == validArgumentCount)
              {
                  wasHandled = emberAfNetworkCommissioningClusterAddWiFiNetworkCallback(aEndpointId, apCommandObj, ssid, credentials,
                                                                                        breadcrumb, timeoutMs);
              }
              break;
          }
          case Clusters::NetworkCommissioning::Commands::Ids::DisableNetwork: {
              expectArgumentCount = 3;
              chip::ByteSpan networkID;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      networkID            = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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)
              {
                  wasHandled = emberAfNetworkCommissioningClusterDisableNetworkCallback(aEndpointId, apCommandObj, networkID,
                                                                                        breadcrumb, timeoutMs);
              }
              break;
          }
          case Clusters::NetworkCommissioning::Commands::Ids::EnableNetwork: {
              expectArgumentCount = 3;
              chip::ByteSpan networkID;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      networkID            = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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)
              {
                  wasHandled = emberAfNetworkCommissioningClusterEnableNetworkCallback(aEndpointId, apCommandObj, networkID,
                                                                                       breadcrumb, timeoutMs);
              }
              break;
          }
          case Clusters::NetworkCommissioning::Commands::Ids::GetLastNetworkCommissioningResult: {
              expectArgumentCount = 1;
              uint32_t timeoutMs;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(timeoutMs);
                      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 && 1 == validArgumentCount)
              {
                  wasHandled = emberAfNetworkCommissioningClusterGetLastNetworkCommissioningResultCallback(aEndpointId, apCommandObj,
                                                                                                           timeoutMs);
              }
              break;
          }
          case Clusters::NetworkCommissioning::Commands::Ids::RemoveNetwork: {
              expectArgumentCount = 3;
              chip::ByteSpan NetworkID;
              uint64_t Breadcrumb;
              uint32_t TimeoutMs;
              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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      NetworkID            = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(Breadcrumb);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(TimeoutMs);
                      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)
              {
                  wasHandled = emberAfNetworkCommissioningClusterRemoveNetworkCallback(aEndpointId, apCommandObj, NetworkID,
                                                                                       Breadcrumb, TimeoutMs);
              }
              break;
          }
          case Clusters::NetworkCommissioning::Commands::Ids::ScanNetworks: {
              expectArgumentCount = 3;
              chip::ByteSpan ssid;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      ssid                 = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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)
              {
                  wasHandled =
                      emberAfNetworkCommissioningClusterScanNetworksCallback(aEndpointId, apCommandObj, ssid, breadcrumb, timeoutMs);
              }
              break;
          }
          case Clusters::NetworkCommissioning::Commands::Ids::UpdateWiFiNetwork: {
              expectArgumentCount = 4;
              chip::ByteSpan ssid;
              chip::ByteSpan credentials;
              uint64_t breadcrumb;
              uint32_t timeoutMs;
              bool argExists[4];
  
              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 < 4)
                  {
                      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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      ssid                 = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      credentials          = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(breadcrumb);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(timeoutMs);
                      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 && 4 == validArgumentCount)
              {
                  wasHandled = emberAfNetworkCommissioningClusterUpdateWiFiNetworkCallback(aEndpointId, apCommandObj, ssid,
                                                                                           credentials, breadcrumb, timeoutMs);
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 Clusters::NetworkCommissioning::Id, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id,
                                          Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
              ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, Clusters::NetworkCommissioning::Id);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             Clusters::NetworkCommissioning::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=%" CHIP_ERROR_FORMAT
                          ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError),
                          ChipError::FormatError(TLVUnpackError), currentDecodeTagId);
          // A command with no arguments would never write currentDecodeTagId.  If
          // progress logging is also disabled, it would look unused.  Silence that
          // warning.
          UNUSED_VAR(currentDecodeTagId);
      }
  }
  
  } // namespace NetworkCommissioning
  
  namespace OperationalCredentials {
  
  void DispatchServerCommand(app::CommandHandler * 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 Clusters::OperationalCredentials::Commands::Ids::AddNOC: {
              expectArgumentCount = 4;
              chip::ByteSpan NOCArray;
              chip::ByteSpan IPKValue;
              chip::NodeId CaseAdminNode;
              uint16_t AdminVendorId;
              bool argExists[4];
  
              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 < 4)
                  {
                      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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      NOCArray             = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 1: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      IPKValue             = chip::ByteSpan(data, aDataTlv.GetLength());
                  }
                  break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(CaseAdminNode);
                      break;
                  case 3:
                      TLVUnpackError = aDataTlv.Get(AdminVendorId);
                      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 && 4 == validArgumentCount)
              {
                  wasHandled = emberAfOperationalCredentialsClusterAddNOCCallback(aEndpointId, apCommandObj, NOCArray, IPKValue,
                                                                                  CaseAdminNode, AdminVendorId);
              }
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::AddTrustedRootCertificate: {
              expectArgumentCount = 1;
              chip::ByteSpan RootCertificate;
              bool argExists[1];
  
              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 < 1)
                  {
                      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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      RootCertificate      = 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 && 1 == validArgumentCount)
              {
                  wasHandled = emberAfOperationalCredentialsClusterAddTrustedRootCertificateCallback(aEndpointId, apCommandObj,
                                                                                                     RootCertificate);
              }
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::OpCSRRequest: {
              expectArgumentCount = 1;
              chip::ByteSpan CSRNonce;
              bool argExists[1];
  
              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 < 1)
                  {
                      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: {
                      const uint8_t * data = nullptr;
                      TLVUnpackError       = aDataTlv.GetDataPtr(data);
                      CSRNonce             = 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 && 1 == validArgumentCount)
              {
                  wasHandled = emberAfOperationalCredentialsClusterOpCSRRequestCallback(aEndpointId, apCommandObj, CSRNonce);
              }
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::RemoveAllFabrics: {
  
              wasHandled = emberAfOperationalCredentialsClusterRemoveAllFabricsCallback(aEndpointId, apCommandObj);
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::RemoveFabric: {
              expectArgumentCount = 3;
              chip::FabricId FabricId;
              chip::NodeId NodeId;
              uint16_t VendorId;
              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(FabricId);
                      break;
                  case 1:
                      TLVUnpackError = aDataTlv.Get(NodeId);
                      break;
                  case 2:
                      TLVUnpackError = aDataTlv.Get(VendorId);
                      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)
              {
                  wasHandled =
                      emberAfOperationalCredentialsClusterRemoveFabricCallback(aEndpointId, apCommandObj, FabricId, NodeId, VendorId);
              }
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::RemoveTrustedRootCertificate: {
              expectArgumentCount = 1;
              chip::ByteSpan TrustedRootIdentifier;
              bool argExists[1];
  
              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 < 1)
                  {
                      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: {
                      const uint8_t * data  = nullptr;
                      TLVUnpackError        = aDataTlv.GetDataPtr(data);
                      TrustedRootIdentifier = 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 && 1 == validArgumentCount)
              {
                  wasHandled = emberAfOperationalCredentialsClusterRemoveTrustedRootCertificateCallback(aEndpointId, apCommandObj,
                                                                                                        TrustedRootIdentifier);
              }
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::SetFabric: {
              expectArgumentCount = 1;
              uint16_t VendorId;
              bool argExists[1];
  
              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 < 1)
                  {
                      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(VendorId);
                      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 && 1 == validArgumentCount)
              {
                  wasHandled = emberAfOperationalCredentialsClusterSetFabricCallback(aEndpointId, apCommandObj, VendorId);
              }
              break;
          }
          case Clusters::OperationalCredentials::Commands::Ids::UpdateFabricLabel: {
              expectArgumentCount = 1;
              const uint8_t * Label;
              bool argExists[1];
  
              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 < 1)
                  {
                      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:
                      // TODO(#5542): The cluster handlers should accept a ByteSpan for all string types.
                      TLVUnpackError = aDataTlv.GetDataPtr(Label);
                      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 && 1 == validArgumentCount)
              {
                  wasHandled = emberAfOperationalCredentialsClusterUpdateFabricLabelCallback(aEndpointId, apCommandObj,
                                                                                             const_cast<uint8_t *>(Label));
              }
              break;
          }
          default: {
              // Unrecognized command ID, error status will apply.
              chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                                 0, // GroupId
                                                                 Clusters::OperationalCredentials::Id, aCommandId,
                                                                 (chip::app::CommandPathFlags::kEndpointIdValid) };
              apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                          Protocols::SecureChannel::Id,
                                          Protocols::InteractionModel::ProtocolCode::UnsupportedCommand);
              ChipLogError(Zcl, "Unknown command %" PRIx32 " for cluster %" PRIx32, aCommandId, Clusters::OperationalCredentials::Id);
              return;
          }
          }
      }
  
      if (CHIP_NO_ERROR != TLVError || CHIP_NO_ERROR != TLVUnpackError || expectArgumentCount != validArgumentCount || !wasHandled)
      {
          chip::app::CommandPathParams returnStatusParam = { aEndpointId,
                                                             0, // GroupId
                                                             Clusters::OperationalCredentials::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=%" CHIP_ERROR_FORMAT
                          ", UnpackError=%" CHIP_ERROR_FORMAT " (last decoded tag = %" PRIu32,
                          validArgumentCount, expectArgumentCount, ChipError::FormatError(TLVError),
                          ChipError::FormatError(TLVUnpackError), currentDecodeTagId);
          // A command with no arguments would never write currentDecodeTagId.  If
          // progress logging is also disabled, it would look unused.  Silence that
          // warning.
          UNUSED_VAR(currentDecodeTagId);
      }
  }
  
  } // namespace OperationalCredentials
  
  } // namespace clusters
  
  void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
                                    chip::TLV::TLVReader & aReader, CommandHandler * apCommandObj)
  {
      ChipLogDetail(Zcl, "Received Cluster Command: Cluster=%" PRIx32 " Command=%" PRIx32 " Endpoint=%" PRIx16, aClusterId,
                    aCommandId, aEndPointId);
      Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId);
      TLV::TLVType dataTlvType;
      SuccessOrExit(aReader.EnterContainer(dataTlvType));
      switch (aClusterId)
      {
      case Clusters::DiagnosticLogs::Id:
          clusters::DiagnosticLogs::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case Clusters::GeneralCommissioning::Id:
          clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case Clusters::NetworkCommissioning::Id:
          clusters::NetworkCommissioning::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      case Clusters::OperationalCredentials::Id:
          clusters::OperationalCredentials::DispatchServerCommand(apCommandObj, aCommandId, aEndPointId, aReader);
          break;
      default:
          // Unrecognized cluster ID, error status will apply.
          chip::app::CommandPathParams returnStatusParam = { aEndPointId,
                                                             0, // GroupId
                                                             aClusterId, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                      Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
          ChipLogError(Zcl, "Unknown cluster %" PRIx32, aClusterId);
          break;
      }
  exit:
      Compatibility::ResetEmberAfObjects();
      aReader.ExitContainer(dataTlvType);
  }
  
  void DispatchSingleClusterResponseCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
                                            chip::TLV::TLVReader & aReader, CommandSender * apCommandObj)
  {
      ChipLogDetail(Zcl, "Received Cluster Command: Cluster=%" PRIx32 " Command=%" PRIx32 " Endpoint=%" PRIx16, aClusterId,
                    aCommandId, aEndPointId);
      Compatibility::SetupEmberAfObjects(apCommandObj, aClusterId, aCommandId, aEndPointId);
      TLV::TLVType dataTlvType;
      SuccessOrExit(aReader.EnterContainer(dataTlvType));
      switch (aClusterId)
      {
      default:
          // Unrecognized cluster ID, error status will apply.
          chip::app::CommandPathParams returnStatusParam = { aEndPointId,
                                                             0, // GroupId
                                                             aClusterId, aCommandId,
                                                             (chip::app::CommandPathFlags::kEndpointIdValid) };
          apCommandObj->AddStatusCode(returnStatusParam, Protocols::SecureChannel::GeneralStatusCode::kNotFound,
                                      Protocols::SecureChannel::Id, Protocols::InteractionModel::ProtocolCode::InvalidCommand);
          ChipLogError(Zcl, "Unknown cluster %" PRIx32, aClusterId);
          break;
      }
  exit:
      Compatibility::ResetEmberAfObjects();
      aReader.ExitContainer(dataTlvType);
  }
  
  } // namespace app
  } // namespace chip
  