Line data Source code
1 : /* 2 : * 3 : * Copyright (c) 2020 Project CHIP Authors 4 : * 5 : * Licensed under the Apache License, Version 2.0 (the "License"); 6 : * you may not use this file except in compliance with the License. 7 : * You may obtain a copy of the License at 8 : * 9 : * http://www.apache.org/licenses/LICENSE-2.0 10 : * 11 : * Unless required by applicable law or agreed to in writing, software 12 : * distributed under the License is distributed on an "AS IS" BASIS, 13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 : * See the License for the specific language governing permissions and 15 : * limitations under the License. 16 : */ 17 : 18 : #include "SetupPayloadHelper.h" 19 : #include "ManualSetupPayloadGenerator.h" 20 : #include "QRCodeSetupPayloadGenerator.h" 21 : #include "SetupPayload.h" 22 : #include <fstream> 23 : #include <utility> 24 : 25 : #include <lib/support/CodeUtils.h> 26 : #include <lib/support/logging/CHIPLogging.h> 27 : 28 : using namespace chip; 29 : 30 : namespace chip { 31 : 32 : enum SetupPayloadKey 33 : { 34 : SetupPayloadKey_Version, 35 : SetupPayloadKey_VendorID, 36 : SetupPayloadKey_ProductID, 37 : SetupPayloadKey_CommissioningFlow, 38 : SetupPayloadKey_RendezVousInformation, 39 : SetupPayloadKey_Discriminator, 40 : SetupPayloadKey_SetupPINCode, 41 : }; 42 : 43 : struct SetupPayloadParameter 44 : { 45 : SetupPayloadKey key; 46 : std::string stringValue; 47 : uint64_t uintValue; 48 : }; 49 : 50 0 : static CHIP_ERROR resolveSetupPayloadParameter(SetupPayloadParameter & parameter, const std::string & key, 51 : const std::string & value) 52 : { 53 0 : bool isUnsignedInt = true; 54 0 : bool shouldHaveValue = true; 55 0 : if (key == "version") 56 : { 57 0 : parameter.key = SetupPayloadKey_Version; 58 : } 59 0 : else if (key == "vendorID") 60 : { 61 0 : parameter.key = SetupPayloadKey_VendorID; 62 : } 63 0 : else if (key == "productID") 64 : { 65 0 : parameter.key = SetupPayloadKey_ProductID; 66 : } 67 0 : else if (key == "commissioningFlow") 68 : { 69 0 : parameter.key = SetupPayloadKey_CommissioningFlow; 70 : } 71 0 : else if (key == "rendezVousInformation") 72 : { 73 0 : parameter.key = SetupPayloadKey_RendezVousInformation; 74 : } 75 0 : else if (key == "discriminator") 76 : { 77 0 : parameter.key = SetupPayloadKey_Discriminator; 78 : } 79 0 : else if (key == "setUpPINCode") 80 : { 81 0 : parameter.key = SetupPayloadKey_SetupPINCode; 82 : } 83 : else 84 : { 85 0 : return CHIP_ERROR_INVALID_ARGUMENT; 86 : } 87 0 : if (shouldHaveValue && value.length() > 0) 88 : { 89 0 : if (isUnsignedInt) 90 : { 91 0 : parameter.uintValue = stoul(value, nullptr, 10); 92 : } 93 : else 94 : { 95 0 : parameter.stringValue = value; 96 : } 97 : } 98 0 : else if (shouldHaveValue) 99 : { 100 0 : return CHIP_ERROR_INVALID_ARGUMENT; 101 : } 102 0 : return CHIP_NO_ERROR; 103 : } 104 : 105 0 : static CHIP_ERROR addParameter(SetupPayload & setupPayload, const SetupPayloadParameter & parameter) 106 : { 107 0 : switch (parameter.key) 108 : { 109 0 : case SetupPayloadKey_Version: 110 0 : ChipLogDetail(SetupPayload, "Loaded version: %u", (uint8_t) parameter.uintValue); 111 0 : setupPayload.version = static_cast<uint8_t>(parameter.uintValue); 112 0 : break; 113 0 : case SetupPayloadKey_VendorID: 114 0 : ChipLogDetail(SetupPayload, "Loaded vendorID: %u", (uint16_t) parameter.uintValue); 115 0 : setupPayload.vendorID = static_cast<uint16_t>(parameter.uintValue); 116 0 : break; 117 0 : case SetupPayloadKey_ProductID: 118 0 : ChipLogDetail(SetupPayload, "Loaded productID: %u", (uint16_t) parameter.uintValue); 119 0 : setupPayload.productID = static_cast<uint16_t>(parameter.uintValue); 120 0 : break; 121 0 : case SetupPayloadKey_CommissioningFlow: 122 0 : ChipLogDetail(SetupPayload, "Commissioning flow: %u", (uint8_t) parameter.uintValue); 123 0 : setupPayload.commissioningFlow = static_cast<CommissioningFlow>(parameter.uintValue); 124 0 : break; 125 0 : case SetupPayloadKey_RendezVousInformation: 126 0 : ChipLogDetail(SetupPayload, "Loaded rendezvousInfo: %u", (uint16_t) parameter.uintValue); 127 0 : setupPayload.rendezvousInformation.SetValue(RendezvousInformationFlags().SetRaw( 128 0 : static_cast<std::underlying_type_t<RendezvousInformationFlag>>(parameter.uintValue))); 129 0 : break; 130 0 : case SetupPayloadKey_Discriminator: 131 0 : ChipLogDetail(SetupPayload, "Loaded discriminator: %u", (uint16_t) parameter.uintValue); 132 0 : setupPayload.discriminator.SetLongValue(static_cast<uint16_t>(parameter.uintValue)); 133 0 : break; 134 0 : case SetupPayloadKey_SetupPINCode: 135 0 : ChipLogDetail(SetupPayload, "Loaded setupPinCode: %lu", (unsigned long) parameter.uintValue); 136 0 : setupPayload.setUpPINCode = static_cast<uint32_t>(parameter.uintValue); 137 0 : break; 138 0 : default: 139 0 : return CHIP_ERROR_INVALID_ARGUMENT; 140 : } 141 0 : return CHIP_NO_ERROR; 142 : } 143 : 144 0 : CHIP_ERROR loadPayloadFromFile(SetupPayload & setupPayload, const std::string & filePath) 145 : { 146 0 : std::ifstream fileStream(filePath); 147 0 : VerifyOrReturnError(!fileStream.fail(), CHIP_ERROR_INVALID_ARGUMENT); 148 : 149 0 : while (fileStream) 150 : { 151 0 : std::string key; 152 0 : std::string value; 153 0 : SetupPayloadParameter parameter; 154 : 155 0 : getline(fileStream, key, ' '); 156 0 : fileStream >> value; 157 0 : fileStream.ignore(); 158 : 159 0 : if (key.length() == 0) 160 : { 161 0 : continue; 162 : } 163 0 : ReturnErrorOnFailure(resolveSetupPayloadParameter(parameter, key, value)); 164 : 165 0 : ReturnErrorOnFailure(addParameter(setupPayload, parameter)); 166 0 : } 167 0 : return CHIP_NO_ERROR; 168 0 : } 169 : 170 0 : CHIP_ERROR generateQRCodeFromFilePath(std::string filePath, std::string & outCode) 171 : { 172 0 : SetupPayload setupPayload; 173 0 : CHIP_ERROR err = loadPayloadFromFile(setupPayload, std::move(filePath)); 174 0 : if (err != CHIP_NO_ERROR) 175 : { 176 0 : return err; 177 : } 178 0 : QRCodeSetupPayloadGenerator generator(setupPayload); 179 0 : err = generator.payloadBase38Representation(outCode); 180 0 : return err; 181 0 : } 182 : 183 0 : CHIP_ERROR generateManualCodeFromFilePath(std::string filePath, std::string & outCode) 184 : { 185 0 : SetupPayload setupPayload; 186 0 : CHIP_ERROR err = loadPayloadFromFile(setupPayload, std::move(filePath)); 187 0 : if (err != CHIP_NO_ERROR) 188 : { 189 0 : return err; 190 : } 191 0 : ManualSetupPayloadGenerator generator(setupPayload); 192 0 : err = generator.payloadDecimalStringRepresentation(outCode); 193 0 : return err; 194 0 : } 195 : } // namespace chip