blob: 3dcada6a05128b8eed16f4579f636d979d5f4004 [file] [log] [blame]
/*
* Copyright (c) 2024 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 "FabricBridge.h"
#include <fabric-bridge-common/BridgedDevice.h>
#include <fabric-bridge-common/BridgedDeviceManager.h>
#include <app/clusters/ecosystem-information-server/ecosystem-information-server.h>
#include <lib/core/CHIPError.h>
#include <string>
using namespace chip;
namespace bridge {
FabricBridge FabricBridge::sInstance;
FabricBridge & FabricBridge::Instance()
{
return sInstance;
}
CHIP_ERROR FabricBridge::AddSynchronizedDevice(const SynchronizedDevice & data)
{
ChipLogProgress(NotSpecified, "Received AddSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", data.id.GetFabricIndex(),
ChipLogValueX64(data.id.GetNodeId()));
// Create a new BridgedDevice and set it as reachable
auto device = std::make_unique<BridgedDevice>(data.id);
device->SetReachable(true);
// Initialize BridgedDevice attributes from data
BridgedDevice::BridgedAttributes attributes;
if (data.uniqueId.has_value())
{
attributes.uniqueId = data.uniqueId.value();
}
if (data.vendorName.has_value())
{
attributes.vendorName = data.vendorName.value();
}
if (data.vendorId.has_value())
{
attributes.vendorId = data.vendorId.value();
}
if (data.productName.has_value())
{
attributes.productName = data.productName.value();
}
if (data.productId.has_value())
{
attributes.productId = data.productId.value();
}
if (data.nodeLabel.has_value())
{
attributes.nodeLabel = data.nodeLabel.value();
}
if (data.hardwareVersion.has_value())
{
attributes.hardwareVersion = data.hardwareVersion.value();
}
if (data.hardwareVersionString.has_value())
{
attributes.hardwareVersionString = data.hardwareVersionString.value();
}
if (data.softwareVersion.has_value())
{
attributes.softwareVersion = data.softwareVersion.value();
}
if (data.softwareVersionString.has_value())
{
attributes.softwareVersionString = data.softwareVersionString.value();
}
// Set bridged device attributes and ICD status
device->SetBridgedAttributes(attributes);
device->SetIcd(data.isIcd.value_or(false));
// Add the device to the bridge manager with a parent endpoint
auto result = BridgedDeviceManager::Instance().AddDeviceEndpoint(std::move(device), /* parentEndpointId= */ 1);
if (!result.has_value())
{
ChipLogError(NotSpecified, "Failed to add device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(),
ChipLogValueX64(data.id.GetNodeId()));
return CHIP_ERROR_ENDPOINT_POOL_FULL;
}
// Retrieve and verify the added device by ScopedNodeId
BridgedDevice * addedDevice = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(data.id);
VerifyOrDie(addedDevice);
ChipLogProgress(NotSpecified, "Added device with Id=[%d:0x" ChipLogFormatX64 "]", data.id.GetFabricIndex(),
ChipLogValueX64(data.id.GetNodeId()));
// Add the Ecosystem Information Cluster to the device's endpoint
CHIP_ERROR err =
app::Clusters::EcosystemInformation::EcosystemInformationServer::Instance().AddEcosystemInformationClusterToEndpoint(
addedDevice->GetEndpointId());
if (err != CHIP_NO_ERROR)
{
ChipLogError(NotSpecified, "Failed to add Ecosystem Information Cluster to endpoint %u: %" CHIP_ERROR_FORMAT,
addedDevice->GetEndpointId(), err.Format());
}
return err;
}
CHIP_ERROR FabricBridge::RemoveSynchronizedDevice(ScopedNodeId scopedNodeId)
{
ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
ChipLogValueX64(scopedNodeId.GetNodeId()));
auto removedIdx = BridgedDeviceManager::Instance().RemoveDeviceByScopedNodeId(scopedNodeId);
if (!removedIdx.has_value())
{
ChipLogError(NotSpecified, "Failed to remove device with Id=[%d:0x" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
ChipLogValueX64(scopedNodeId.GetNodeId()));
return CHIP_ERROR_NOT_FOUND;
}
return CHIP_NO_ERROR;
}
CHIP_ERROR FabricBridge::ActiveChanged(ScopedNodeId scopedNodeId, uint32_t promisedActiveDurationMs)
{
ChipLogProgress(NotSpecified, "Received ActiveChanged: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
ChipLogValueX64(scopedNodeId.GetNodeId()));
auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(scopedNodeId);
if (device == nullptr)
{
ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]",
scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()));
return CHIP_ERROR_NOT_FOUND;
}
device->LogActiveChangeEvent(promisedActiveDurationMs);
return CHIP_NO_ERROR;
}
CHIP_ERROR FabricBridge::AdminCommissioningAttributeChanged(const AdministratorCommissioningChanged & data)
{
ChipLogProgress(NotSpecified, "Received CADMIN attribute change: Id=[%d:" ChipLogFormatX64 "]", data.id.GetFabricIndex(),
ChipLogValueX64(data.id.GetNodeId()));
auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(data.id);
if (device == nullptr)
{
ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]",
data.id.GetFabricIndex(), ChipLogValueX64(data.id.GetNodeId()));
return CHIP_ERROR_NOT_FOUND;
}
BridgedDevice::AdminCommissioningAttributes adminCommissioningAttributes;
VerifyOrReturnError(data.windowStatus <
app::Clusters::AdministratorCommissioning::CommissioningWindowStatusEnum::kUnknownEnumValue,
CHIP_ERROR_INVALID_ARGUMENT);
adminCommissioningAttributes.commissioningWindowStatus = data.windowStatus;
if (data.openerFabricIndex.has_value())
{
VerifyOrReturnError(data.openerFabricIndex >= kMinValidFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(data.openerFabricIndex <= kMaxValidFabricIndex, CHIP_ERROR_INVALID_ARGUMENT);
adminCommissioningAttributes.openerFabricIndex = data.openerFabricIndex;
}
if (data.openerVendorId.has_value())
{
VerifyOrReturnError(data.openerVendorId != VendorId::NotSpecified, CHIP_ERROR_INVALID_ARGUMENT);
adminCommissioningAttributes.openerVendorId = data.openerVendorId;
}
device->SetAdminCommissioningAttributes(adminCommissioningAttributes);
return CHIP_NO_ERROR;
}
CHIP_ERROR FabricBridge::DeviceReachableChanged(ScopedNodeId scopedNodeId, bool reachability)
{
ChipLogProgress(NotSpecified, "Received device reachable changed: Id=[%d:" ChipLogFormatX64 "]", scopedNodeId.GetFabricIndex(),
ChipLogValueX64(scopedNodeId.GetNodeId()));
auto * device = BridgedDeviceManager::Instance().GetDeviceByScopedNodeId(scopedNodeId);
if (device == nullptr)
{
ChipLogError(NotSpecified, "Could not find bridged device associated with Id=[%d:0x" ChipLogFormatX64 "]",
scopedNodeId.GetFabricIndex(), ChipLogValueX64(scopedNodeId.GetNodeId()));
return CHIP_ERROR_NOT_FOUND;
}
device->ReachableChanged(reachability);
return CHIP_NO_ERROR;
}
} // namespace bridge