blob: d60c46d42ce5b01a36ed4e89f81e09961ef69400 [file] [log] [blame]
/*
* Copyright (c) 2022 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 "CommissionerCommands.h"
constexpr uint16_t kPayloadMaxSize = 64;
CHIP_ERROR
CommissionerCommands::PairWithCode(const char * identity,
const chip::app::Clusters::CommissionerCommands::Commands::PairWithCode::Type & value)
{
VerifyOrReturnError(value.payload.size() > 0 && value.payload.size() < kPayloadMaxSize, CHIP_ERROR_INVALID_ARGUMENT);
GetCommissioner(identity).RegisterPairingDelegate(this);
char code[kPayloadMaxSize];
memset(code, '\0', sizeof(code));
memcpy(code, value.payload.data(), value.payload.size());
ChipLogError(chipTool, "Pairing Code is %s", code);
// To reduce the scanning latency in some setups, and since the primary use for PairWithCode is to commission a device to
// another commissioner, assume that the commissionable device is available on the network.
auto discoveryType = chip::Controller::DiscoveryType::kDiscoveryNetworkOnly;
if (value.discoverOnce.ValueOr(false))
{
discoveryType = chip::Controller::DiscoveryType::kDiscoveryNetworkOnlyWithoutPASEAutoRetry;
}
return GetCommissioner(identity).PairDevice(value.nodeId, code, discoveryType);
}
CHIP_ERROR CommissionerCommands::Unpair(const char * identity,
const chip::app::Clusters::CommissionerCommands::Commands::Unpair::Type & value)
{
return GetCommissioner(identity).UnpairDevice(value.nodeId);
}
CHIP_ERROR CommissionerCommands::GetCommissionerNodeId(
const char * identity, const chip::app::Clusters::CommissionerCommands::Commands::GetCommissionerNodeId::Type & value)
{
chip::GetCommissionerNodeIdResponse data;
data.nodeId = GetCommissioner(identity).GetNodeId();
chip::app::StatusIB status;
status.mStatus = chip::Protocols::InteractionModel::Status::Success;
constexpr uint32_t kMaxDataLen = 128;
uint8_t * buffer = static_cast<uint8_t *>(chip::Platform::MemoryCalloc(sizeof(uint8_t), kMaxDataLen));
if (buffer == nullptr)
{
ChipLogError(chipTool, "Can not allocate commissioner node id data: %s", chip::ErrorStr(CHIP_ERROR_NO_MEMORY));
return CHIP_ERROR_NO_MEMORY;
}
chip::TLV::TLVWriter writer;
writer.Init(buffer, kMaxDataLen);
CHIP_ERROR err = data.Encode(writer, chip::TLV::AnonymousTag());
if (CHIP_NO_ERROR != err)
{
ChipLogError(chipTool, "Can not encode commissioner node id data: %s", chip::ErrorStr(err));
return err;
}
uint32_t dataLen = writer.GetLengthWritten();
writer.Finalize();
chip::TLV::TLVReader reader;
reader.Init(buffer, dataLen);
reader.Next();
OnResponse(status, &reader);
chip::Platform::MemoryFree(buffer);
return CHIP_NO_ERROR;
}
chip::app::StatusIB ConvertToStatusIB(CHIP_ERROR err)
{
using chip::app::StatusIB;
using namespace chip;
using namespace chip::Protocols::InteractionModel;
using namespace chip::app::Clusters::OperationalCredentials;
if (CHIP_ERROR_INVALID_PUBLIC_KEY == err)
{
return StatusIB(Status::Failure, to_underlying(NodeOperationalCertStatusEnum::kInvalidPublicKey));
}
if (CHIP_ERROR_WRONG_NODE_ID == err)
{
return StatusIB(Status::Failure, to_underlying(NodeOperationalCertStatusEnum::kInvalidNodeOpId));
}
if (CHIP_ERROR_UNSUPPORTED_CERT_FORMAT == err)
{
return StatusIB(Status::Failure, to_underlying(NodeOperationalCertStatusEnum::kInvalidNOC));
}
if (CHIP_ERROR_FABRIC_EXISTS == err)
{
return StatusIB(Status::Failure, to_underlying(NodeOperationalCertStatusEnum::kFabricConflict));
}
if (CHIP_ERROR_INVALID_FABRIC_INDEX == err)
{
return StatusIB(Status::Failure, to_underlying(NodeOperationalCertStatusEnum::kInvalidFabricIndex));
}
return StatusIB(err);
}
void CommissionerCommands::OnStatusUpdate(DevicePairingDelegate::Status status)
{
switch (status)
{
case DevicePairingDelegate::Status::SecurePairingSuccess:
ChipLogProgress(chipTool, "Secure Pairing Success");
break;
case DevicePairingDelegate::Status::SecurePairingFailed:
ChipLogError(chipTool, "Secure Pairing Failed");
OnResponse(ConvertToStatusIB(CHIP_ERROR_INCORRECT_STATE), nullptr);
break;
}
}
void CommissionerCommands::OnPairingComplete(CHIP_ERROR err)
{
if (CHIP_NO_ERROR != err)
{
ChipLogError(chipTool, "Pairing Complete Failure: %s", ErrorStr(err));
OnResponse(ConvertToStatusIB(err), nullptr);
}
}
void CommissionerCommands::OnPairingDeleted(CHIP_ERROR err)
{
if (err != CHIP_NO_ERROR)
{
ChipLogError(chipTool, "Pairing Delete Failure: %s", ErrorStr(err));
}
OnResponse(ConvertToStatusIB(err), nullptr);
}
void CommissionerCommands::OnCommissioningComplete(chip::NodeId nodeId, CHIP_ERROR err)
{
if (err != CHIP_NO_ERROR)
{
ChipLogError(chipTool, "Commissioning Complete Failure: %s", ErrorStr(err));
}
OnResponse(ConvertToStatusIB(err), nullptr);
}