blob: 3b158b876bf033268e13da73147592f5e67f7504 [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 "DeviceManager.h"
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/ConcreteAttributePath.h>
#include <app/EventLogging.h>
#include <app/reporting/reporting.h>
#include <app/server/Server.h>
#include <app/util/af-types.h>
#include <app/util/attribute-storage.h>
#include <app/util/endpoint-config-api.h>
#include <app/util/util.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/ZclString.h>
#include <cstdio>
#include <string>
using namespace chip;
using namespace chip::app;
using namespace chip::Credentials;
using namespace chip::Inet;
using namespace chip::Transport;
using namespace chip::DeviceLayer;
using namespace chip::app::Clusters;
namespace {
constexpr uint8_t kMaxRetries = 10;
} // namespace
// Define the static member
DeviceManager DeviceManager::sInstance;
void DeviceManager::Init()
{
memset(mDevices, 0, sizeof(mDevices));
mFirstDynamicEndpointId = static_cast<chip::EndpointId>(
static_cast<int>(emberAfEndpointFromIndex(static_cast<uint16_t>(emberAfFixedEndpointCount() - 1))) + 1);
mCurrentEndpointId = mFirstDynamicEndpointId;
}
int DeviceManager::AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep,
const chip::Span<const EmberAfDeviceType> & deviceTypeList,
const chip::Span<chip::DataVersion> & dataVersionStorage, chip::EndpointId parentEndpointId)
{
uint8_t index = 0;
while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
{
if (nullptr == mDevices[index])
{
mDevices[index] = dev;
CHIP_ERROR err;
int retryCount = 0;
while (retryCount < kMaxRetries)
{
DeviceLayer::StackLock lock;
dev->SetEndpointId(mCurrentEndpointId);
dev->SetParentEndpointId(parentEndpointId);
err =
emberAfSetDynamicEndpoint(index, mCurrentEndpointId, ep, dataVersionStorage, deviceTypeList, parentEndpointId);
if (err == CHIP_NO_ERROR)
{
ChipLogProgress(NotSpecified, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(),
mCurrentEndpointId, index);
return index;
}
if (err != CHIP_ERROR_ENDPOINT_EXISTS)
{
return -1; // Return error as endpoint addition failed due to an error other than endpoint already exists
}
// Increment the endpoint ID and handle wrap condition
if (++mCurrentEndpointId < mFirstDynamicEndpointId)
{
mCurrentEndpointId = mFirstDynamicEndpointId;
}
retryCount++;
}
ChipLogError(NotSpecified, "Failed to add dynamic endpoint after %d retries", kMaxRetries);
return -1; // Return error as all retries are exhausted
}
index++;
}
ChipLogProgress(NotSpecified, "Failed to add dynamic endpoint: No endpoints available!");
return -1;
}
int DeviceManager::RemoveDeviceEndpoint(Device * dev)
{
uint8_t index = 0;
while (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
{
if (mDevices[index] == dev)
{
DeviceLayer::StackLock lock;
// Silence complaints about unused ep when progress logging
// disabled.
[[maybe_unused]] EndpointId ep = emberAfClearDynamicEndpoint(index);
mDevices[index] = nullptr;
ChipLogProgress(NotSpecified, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index);
return index;
}
index++;
}
return -1;
}
Device * DeviceManager::GetDevice(uint16_t index) const
{
if (index < CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT)
{
return mDevices[index];
}
return nullptr;
}