[ChipTool] Add Payload Parse Command (#3696)

* [ChipTool] Add Payload Parse Command

* [ChipTool] Add Payload Parse Command

* [ChipTool] Restyle issues resolved

* Restyled by whitespace

* Resolve build errors caused by Command.h schema change

Co-authored-by: lijayaku <lijayaku@amazon.com>
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn
index ed4db26..17ed976 100644
--- a/examples/chip-tool/BUILD.gn
+++ b/examples/chip-tool/BUILD.gn
@@ -27,6 +27,7 @@
     "commands/common/NetworkCommand.cpp",
     "commands/echo/EchoCommand.cpp",
     "commands/pairing/PairingCommand.cpp",
+    "commands/payload/ParseCommand.cpp",
     "config/PersistentStorage.cpp",
     "main.cpp",
   ]
diff --git a/examples/chip-tool/README.md b/examples/chip-tool/README.md
index cae687f..bf0cbdf 100644
--- a/examples/chip-tool/README.md
+++ b/examples/chip-tool/README.md
@@ -104,3 +104,24 @@
 with the target cluster name and the target command name
 
     $ chip-tool onoff on
+
+## Using the Client for Setup Payload
+
+### How to parse a setup code
+
+To parse a setup code, run the built executable with the `payload` cluster name
+and the `parse` command
+
+    $ chip-tool payload parse code
+
+#### QR Code
+
+    $ chip-tool payload parse "CH:#####"
+
+#### QR Code with optional Vendor Info
+
+    $ chip-tool chip-tool payload parse "CH:#####"
+
+#### Manual Setup Code
+
+    $ chip-tool payload parse :#####"
diff --git a/examples/chip-tool/commands/payload/Commands.h b/examples/chip-tool/commands/payload/Commands.h
new file mode 100644
index 0000000..83c1124
--- /dev/null
+++ b/examples/chip-tool/commands/payload/Commands.h
@@ -0,0 +1,31 @@
+/*
+ *   Copyright (c) 2020 Project CHIP Authors
+ *   All rights reserved.
+ *
+ *   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.
+ *
+ */
+
+#pragma once
+
+#include "ParseCommand.h"
+
+void registerCommandsPayload(Commands & commands)
+{
+    const char * clusterName      = "Payload";
+    commands_list clusterCommands = {
+        make_unique<ParseCommand>(),
+    };
+
+    commands.Register(clusterName, clusterCommands);
+}
diff --git a/examples/chip-tool/commands/payload/ParseCommand.cpp b/examples/chip-tool/commands/payload/ParseCommand.cpp
new file mode 100644
index 0000000..534efb1
--- /dev/null
+++ b/examples/chip-tool/commands/payload/ParseCommand.cpp
@@ -0,0 +1,104 @@
+/*
+ *   Copyright (c) 2020 Project CHIP Authors
+ *   All rights reserved.
+ *
+ *   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 "ParseCommand.h"
+#include <setup_payload/ManualSetupPayloadParser.h>
+#include <setup_payload/QRCodeSetupPayloadParser.h>
+#include <setup_payload/SetupPayload.h>
+
+using namespace ::chip;
+
+CHIP_ERROR ParseCommand::Run(PersistentStorage & storage, NodeId localId, NodeId remoteId)
+{
+    std::string codeString(mCode);
+    SetupPayload payload;
+
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    err            = Parse(codeString, payload);
+    SuccessOrExit(err);
+
+    err = Print(payload);
+    SuccessOrExit(err);
+exit:
+    return err;
+}
+
+CHIP_ERROR ParseCommand::Print(chip::SetupPayload payload)
+{
+    std::string serialNumber;
+    std::vector<OptionalQRCodeInfo> optionalVendorData;
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    ChipLogProgress(SetupPayload, "RequiresCustomFlow: %u", payload.requiresCustomFlow);
+    ChipLogProgress(SetupPayload, "VendorID: %u", payload.vendorID);
+    ChipLogProgress(SetupPayload, "Version: %u", payload.version);
+    ChipLogProgress(SetupPayload, "ProductID: %u", payload.productID);
+    ChipLogProgress(SetupPayload, "Discriminator: %u", payload.discriminator);
+    ChipLogProgress(SetupPayload, "SetUpPINCode: %u", payload.setUpPINCode);
+    ChipLogProgress(SetupPayload, "RendezvousInformation: %u", payload.rendezvousInformation);
+
+    if (payload.getSerialNumber(serialNumber) == CHIP_NO_ERROR)
+    {
+        ChipLogProgress(SetupPayload, "SerialNumber: %s", serialNumber.c_str());
+    }
+
+    optionalVendorData = payload.getAllOptionalVendorData();
+    for (const OptionalQRCodeInfo & info : optionalVendorData)
+    {
+        if (info.type == optionalQRCodeInfoTypeString)
+        {
+            ChipLogProgress(SetupPayload, "OptionalQRCodeInfo: tag=%u,string value=%s", info.tag, info.data.c_str());
+        }
+        else if (info.type == optionalQRCodeInfoTypeInt32)
+        {
+            ChipLogProgress(SetupPayload, "OptionalQRCodeInfo: tag=%u,int value=%u", info.tag, info.int32);
+        }
+        else
+        {
+            err = CHIP_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    SuccessOrExit(err);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR ParseCommand::Parse(std::string codeString, chip::SetupPayload & payload)
+{
+
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    if (IsQRCode(codeString))
+    {
+        ChipLogDetail(SetupPayload, "Parsing base41Representation: %s", codeString.c_str());
+        err = QRCodeSetupPayloadParser(codeString).populatePayload(payload);
+    }
+    else
+    {
+        ChipLogDetail(SetupPayload, "Parsing decimalRepresentation: %s", codeString.c_str());
+        err = ManualSetupPayloadParser(codeString).populatePayload(payload);
+    }
+
+    return err;
+}
+
+bool ParseCommand::IsQRCode(std::string codeString)
+{
+    return codeString.rfind(QRCODE_PREFIX) == 0;
+}
diff --git a/examples/chip-tool/commands/payload/ParseCommand.h b/examples/chip-tool/commands/payload/ParseCommand.h
new file mode 100644
index 0000000..f7d2a41
--- /dev/null
+++ b/examples/chip-tool/commands/payload/ParseCommand.h
@@ -0,0 +1,36 @@
+/*
+ *   Copyright (c) 2020 Project CHIP Authors
+ *   All rights reserved.
+ *
+ *   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.
+ *
+ */
+
+#pragma once
+
+#include "../common/Command.h"
+#include <setup_payload/SetupPayload.h>
+
+class ParseCommand : public Command
+{
+public:
+    ParseCommand() : Command("parse") { AddArgument("code", &mCode); }
+    CHIP_ERROR Run(PersistentStorage & storage, NodeId localId, NodeId remoteId) override;
+
+private:
+    char * mCode;
+    CHIP_ERROR Parse(std::string codeString, chip::SetupPayload & payload);
+    CHIP_ERROR Print(chip::SetupPayload payload);
+    bool IsQRCode(std::string codeString);
+    const std::string QRCODE_PREFIX = "CH:";
+};
diff --git a/examples/chip-tool/main.cpp b/examples/chip-tool/main.cpp
index 52cec54..a7bf3ec 100644
--- a/examples/chip-tool/main.cpp
+++ b/examples/chip-tool/main.cpp
@@ -21,6 +21,7 @@
 #include "commands/clusters/Commands.h"
 #include "commands/echo/Commands.h"
 #include "commands/pairing/Commands.h"
+#include "commands/payload/Commands.h"
 
 #include <transport/SecurePairingSession.h>
 
@@ -30,8 +31,8 @@
 int main(int argc, char * argv[])
 {
     Commands commands;
-
     registerCommandsEcho(commands);
+    registerCommandsPayload(commands);
     registerCommandsPairing(commands);
     registerClusters(commands);