|  | /* | 
|  | * | 
|  | *    Copyright (c) 2020 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 "SetupPayloadHelper.h" | 
|  | #include "ManualSetupPayloadGenerator.h" | 
|  | #include "QRCodeSetupPayloadGenerator.h" | 
|  | #include "SetupPayload.h" | 
|  | #include <fstream> | 
|  | #include <utility> | 
|  |  | 
|  | #include <lib/support/CodeUtils.h> | 
|  | #include <lib/support/logging/CHIPLogging.h> | 
|  |  | 
|  | using namespace chip; | 
|  |  | 
|  | namespace chip { | 
|  |  | 
|  | enum SetupPayloadKey | 
|  | { | 
|  | SetupPayloadKey_Version, | 
|  | SetupPayloadKey_VendorID, | 
|  | SetupPayloadKey_ProductID, | 
|  | SetupPayloadKey_CommissioningFlow, | 
|  | SetupPayloadKey_RendezVousInformation, | 
|  | SetupPayloadKey_Discriminator, | 
|  | SetupPayloadKey_SetupPINCode, | 
|  | }; | 
|  |  | 
|  | struct SetupPayloadParameter | 
|  | { | 
|  | SetupPayloadKey key; | 
|  | std::string stringValue; | 
|  | uint64_t uintValue; | 
|  | }; | 
|  |  | 
|  | static CHIP_ERROR resolveSetupPayloadParameter(SetupPayloadParameter & parameter, const std::string & key, | 
|  | const std::string & value) | 
|  | { | 
|  | bool isUnsignedInt   = true; | 
|  | bool shouldHaveValue = true; | 
|  | if (key == "version") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_Version; | 
|  | } | 
|  | else if (key == "vendorID") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_VendorID; | 
|  | } | 
|  | else if (key == "productID") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_ProductID; | 
|  | } | 
|  | else if (key == "commissioningFlow") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_CommissioningFlow; | 
|  | } | 
|  | else if (key == "rendezVousInformation") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_RendezVousInformation; | 
|  | } | 
|  | else if (key == "discriminator") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_Discriminator; | 
|  | } | 
|  | else if (key == "setUpPINCode") | 
|  | { | 
|  | parameter.key = SetupPayloadKey_SetupPINCode; | 
|  | } | 
|  | else | 
|  | { | 
|  | return CHIP_ERROR_INVALID_ARGUMENT; | 
|  | } | 
|  | if (shouldHaveValue && value.length() > 0) | 
|  | { | 
|  | if (isUnsignedInt) | 
|  | { | 
|  | parameter.uintValue = stoul(value, nullptr, 10); | 
|  | } | 
|  | else | 
|  | { | 
|  | parameter.stringValue = value; | 
|  | } | 
|  | } | 
|  | else if (shouldHaveValue) | 
|  | { | 
|  | return CHIP_ERROR_INVALID_ARGUMENT; | 
|  | } | 
|  | return CHIP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | static CHIP_ERROR addParameter(SetupPayload & setupPayload, const SetupPayloadParameter & parameter) | 
|  | { | 
|  | switch (parameter.key) | 
|  | { | 
|  | case SetupPayloadKey_Version: | 
|  | ChipLogDetail(SetupPayload, "Loaded version: %u", (uint8_t) parameter.uintValue); | 
|  | setupPayload.version = static_cast<uint8_t>(parameter.uintValue); | 
|  | break; | 
|  | case SetupPayloadKey_VendorID: | 
|  | ChipLogDetail(SetupPayload, "Loaded vendorID: %u", (uint16_t) parameter.uintValue); | 
|  | setupPayload.vendorID = static_cast<uint16_t>(parameter.uintValue); | 
|  | break; | 
|  | case SetupPayloadKey_ProductID: | 
|  | ChipLogDetail(SetupPayload, "Loaded productID: %u", (uint16_t) parameter.uintValue); | 
|  | setupPayload.productID = static_cast<uint16_t>(parameter.uintValue); | 
|  | break; | 
|  | case SetupPayloadKey_CommissioningFlow: | 
|  | ChipLogDetail(SetupPayload, "Commissioning flow: %u", (uint8_t) parameter.uintValue); | 
|  | setupPayload.commissioningFlow = static_cast<CommissioningFlow>(parameter.uintValue); | 
|  | break; | 
|  | case SetupPayloadKey_RendezVousInformation: | 
|  | ChipLogDetail(SetupPayload, "Loaded rendezvousInfo: %u", (uint16_t) parameter.uintValue); | 
|  | setupPayload.rendezvousInformation.SetValue(RendezvousInformationFlags().SetRaw( | 
|  | static_cast<std::underlying_type_t<RendezvousInformationFlag>>(parameter.uintValue))); | 
|  | break; | 
|  | case SetupPayloadKey_Discriminator: | 
|  | ChipLogDetail(SetupPayload, "Loaded discriminator: %u", (uint16_t) parameter.uintValue); | 
|  | setupPayload.discriminator.SetLongValue(static_cast<uint16_t>(parameter.uintValue)); | 
|  | break; | 
|  | case SetupPayloadKey_SetupPINCode: | 
|  | ChipLogDetail(SetupPayload, "Loaded setupPinCode: %lu", (unsigned long) parameter.uintValue); | 
|  | setupPayload.setUpPINCode = static_cast<uint32_t>(parameter.uintValue); | 
|  | break; | 
|  | default: | 
|  | return CHIP_ERROR_INVALID_ARGUMENT; | 
|  | } | 
|  | return CHIP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | CHIP_ERROR loadPayloadFromFile(SetupPayload & setupPayload, const std::string & filePath) | 
|  | { | 
|  | std::ifstream fileStream(filePath); | 
|  | VerifyOrReturnError(!fileStream.fail(), CHIP_ERROR_INVALID_ARGUMENT); | 
|  |  | 
|  | while (fileStream) | 
|  | { | 
|  | std::string key; | 
|  | std::string value; | 
|  | SetupPayloadParameter parameter; | 
|  |  | 
|  | getline(fileStream, key, ' '); | 
|  | fileStream >> value; | 
|  | fileStream.ignore(); | 
|  |  | 
|  | if (key.length() == 0) | 
|  | { | 
|  | continue; | 
|  | } | 
|  | ReturnErrorOnFailure(resolveSetupPayloadParameter(parameter, key, value)); | 
|  |  | 
|  | ReturnErrorOnFailure(addParameter(setupPayload, parameter)); | 
|  | } | 
|  | return CHIP_NO_ERROR; | 
|  | } | 
|  |  | 
|  | CHIP_ERROR generateQRCodeFromFilePath(std::string filePath, std::string & outCode) | 
|  | { | 
|  | SetupPayload setupPayload; | 
|  | CHIP_ERROR err = loadPayloadFromFile(setupPayload, std::move(filePath)); | 
|  | if (err != CHIP_NO_ERROR) | 
|  | { | 
|  | return err; | 
|  | } | 
|  | QRCodeSetupPayloadGenerator generator(setupPayload); | 
|  | err = generator.payloadBase38Representation(outCode); | 
|  | return err; | 
|  | } | 
|  |  | 
|  | CHIP_ERROR generateManualCodeFromFilePath(std::string filePath, std::string & outCode) | 
|  | { | 
|  | SetupPayload setupPayload; | 
|  | CHIP_ERROR err = loadPayloadFromFile(setupPayload, std::move(filePath)); | 
|  | if (err != CHIP_NO_ERROR) | 
|  | { | 
|  | return err; | 
|  | } | 
|  | ManualSetupPayloadGenerator generator(setupPayload); | 
|  | err = generator.payloadDecimalStringRepresentation(outCode); | 
|  | return err; | 
|  | } | 
|  | } // namespace chip |