Skip to content

Commit

Permalink
samples: matter: Refactored bridge manager API for adding devices
Browse files Browse the repository at this point in the history
Changed bridged manager API and adding devices algorithm to allow
requesting usage of specific index and endpoint id.

Signed-off-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no>
  • Loading branch information
kkasperczyk-no committed Aug 21, 2023
1 parent 6fef67a commit c8e3d0e
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 51 deletions.
19 changes: 10 additions & 9 deletions applications/matter_bridge/src/bridged_devices_creator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include "bridged_devices_creator.h"
#include "bridge_manager.h"
#include "bridge_storage_manager.h"
#include "bridged_device_factory.h"
#include "bridged_devices_creator.h"

#include <zephyr/logging/log.h>

Expand All @@ -20,18 +20,17 @@ CHIP_ERROR AddDevice(int deviceType, const char *nodeLabel, BridgedDeviceDataPro
VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INVALID_ARGUMENT,
LOG_ERR("Cannot allocate data provider of given type"));

auto *newBridgedDevice =
BridgeFactory::GetBridgedDeviceFactory().Create(static_cast<BridgedDevice::DeviceType>(deviceType),
nodeLabel,
static_cast<BridgedDevice::DeviceType>(deviceType));
auto *newBridgedDevice = BridgeFactory::GetBridgedDeviceFactory().Create(
static_cast<BridgedDevice::DeviceType>(deviceType), nodeLabel);

if (newBridgedDevice == nullptr) {
delete provider;
LOG_ERR("Cannot allocate Matter device of given type");
return CHIP_ERROR_INTERNAL;
}

CHIP_ERROR err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevice, provider);
uint8_t index = 0;
CHIP_ERROR err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevice, provider, index);

if (err == CHIP_NO_ERROR) {
} else if (err == CHIP_ERROR_INVALID_STRING_LENGTH) {
Expand Down Expand Up @@ -120,8 +119,8 @@ BridgedDeviceDataProvider *CreateBleProvider(int deviceType, const char *nodeLab

CHIP_ERROR BridgedDeviceCreator::CreateDevice(int deviceType, const char *nodeLabel
#ifdef CONFIG_BRIDGED_DEVICE_BT
,
int bleDeviceIndex
,
int bleDeviceIndex
#endif
)
{
Expand All @@ -146,5 +145,7 @@ CHIP_ERROR BridgedDeviceCreator::CreateDevice(int deviceType, const char *nodeLa

CHIP_ERROR BridgedDeviceCreator::RemoveDevice(int endpointId)
{
return BridgeManager::Instance().RemoveBridgedDevice(endpointId);
uint8_t index = 0;

return BridgeManager::Instance().RemoveBridgedDevice(endpointId, index);
}
2 changes: 2 additions & 0 deletions applications/matter_bridge/src/bridged_devices_creator.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#pragma once

#include <lib/core/CHIPError.h>

namespace BridgedDeviceCreator
{
CHIP_ERROR CreateDevice(int deviceType, const char *nodeLabel
Expand Down
152 changes: 113 additions & 39 deletions samples/matter/common/src/bridge/bridge_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,43 @@ void BridgeManager::Init()
false);
}

CHIP_ERROR BridgeManager::AddBridgedDevices(BridgedDevice *aDevice, BridgedDeviceDataProvider *aDataProvider)
CHIP_ERROR BridgeManager::AddBridgedDevices(BridgedDevice *device, BridgedDeviceDataProvider *dataProvider,
uint8_t &devicesPairIndex)
{
aDataProvider->Init();
CHIP_ERROR err = AddDevices(aDevice, aDataProvider);
chip::Optional<uint8_t> index;

return err;
return AddBridgedDevices(device, dataProvider, devicesPairIndex, mCurrentDynamicEndpointId, index);
}

CHIP_ERROR BridgeManager::AddBridgedDevices(BridgedDevice *device, BridgedDeviceDataProvider *dataProvider,
uint8_t &devicesPairIndex, uint16_t endpointId)
{
chip::Optional<uint8_t> index;
index.SetValue(devicesPairIndex);

return AddBridgedDevices(device, dataProvider, devicesPairIndex, endpointId, index);
}

CHIP_ERROR BridgeManager::AddBridgedDevices(BridgedDevice *device, BridgedDeviceDataProvider *dataProvider,
uint8_t &devicesPairIndex, uint16_t endpointId,
chip::Optional<uint8_t> &index)
{
CHIP_ERROR err = AddDevices(device, dataProvider, index, endpointId);

if (err != CHIP_NO_ERROR) {
return err;
}

if (!index.HasValue()) {
return CHIP_ERROR_INTERNAL;
}

devicesPairIndex = index.Value();

return CHIP_NO_ERROR;
}

CHIP_ERROR BridgeManager::RemoveBridgedDevice(uint16_t endpoint)
CHIP_ERROR BridgeManager::RemoveBridgedDevice(uint16_t endpoint, uint8_t &devicesPairIndex)
{
uint8_t index = 0;

Expand All @@ -52,6 +80,7 @@ CHIP_ERROR BridgeManager::RemoveBridgedDevice(uint16_t endpoint)
emberAfClearDynamicEndpoint(index);
if (mDevicesMap.Erase(index)) {
mNumberOfProviders--;
devicesPairIndex = index;
return CHIP_NO_ERROR;
} else {
LOG_ERR("Cannot remove bridged devices under index=%d", index);
Expand All @@ -64,58 +93,103 @@ CHIP_ERROR BridgeManager::RemoveBridgedDevice(uint16_t endpoint)
return CHIP_ERROR_NOT_FOUND;
}

CHIP_ERROR BridgeManager::AddDevices(BridgedDevice *aDevice, BridgedDeviceDataProvider *aDataProvider)
CHIP_ERROR BridgeManager::CreateEndpoint(uint8_t index, uint16_t endpointId)
{
if (!mDevicesMap[index]) {
LOG_ERR("Cannot retrieve bridged device from index %d", index);
return CHIP_ERROR_INTERNAL;
}

auto &storedDevice = mDevicesMap[index]->mDevice;
EmberAfStatus ret = emberAfSetDynamicEndpoint(
index, endpointId, storedDevice->mEp,
Span<DataVersion>(storedDevice->mDataVersion, storedDevice->mDataVersionSize),
Span<const EmberAfDeviceType>(storedDevice->mDeviceTypeList, storedDevice->mDeviceTypeListSize));

if (ret == EMBER_ZCL_STATUS_SUCCESS) {
LOG_INF("Added device to dynamic endpoint %d (index=%d)", endpointId, index);
storedDevice->Init(endpointId);
return CHIP_NO_ERROR;
} else if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS) {
LOG_ERR("Failed to add dynamic endpoint: Internal error!");
RemoveBridgedDevice(endpointId, index); // TODO: check if this
// is ok, we need to
// cleanup the unused
// devices
return CHIP_ERROR_INTERNAL;
} else {
return CHIP_ERROR_SENTINEL;
}
}

CHIP_ERROR BridgeManager::AddDevices(BridgedDevice *aDevice, BridgedDeviceDataProvider *aDataProvider,
chip::Optional<uint8_t> &devicesPairIndex, uint16_t endpointId)
{
uint8_t index = 0;
CHIP_ERROR err;

Platform::UniquePtr<BridgedDevice> device(aDevice);
Platform::UniquePtr<BridgedDeviceDataProvider> provider(aDataProvider);
VerifyOrReturnError(device && provider, CHIP_ERROR_INTERNAL);

provider->Init();

/* Maximum number of Matter bridged devices is controlled inside mDevicesMap,
but the data providers may be created independently, so let's ensure we do not
violate the maximum number of supported instances. */
VerifyOrReturnError(!mDevicesMap.IsFull(), CHIP_ERROR_INTERNAL);
VerifyOrReturnError(mNumberOfProviders + 1 <= kMaxDataProviders, CHIP_ERROR_INTERNAL);
mNumberOfProviders++;

while (index < kMaxBridgedDevices) {
/* Find the first empty index in the bridged devices list */
if (!mDevicesMap.Contains(index)) {
mDevicesMap.Insert(index, DevicePair(std::move(device), std::move(provider)));
EmberAfStatus ret;
while (true) {
if (!mDevicesMap[index]) {
LOG_ERR("Cannot retrieve bridged device from index %d", index);
return CHIP_ERROR_INTERNAL;
}
auto &storedDevice = mDevicesMap[index]->mDevice;
ret = emberAfSetDynamicEndpoint(
index, mCurrentDynamicEndpointId, storedDevice->mEp,
Span<DataVersion>(storedDevice->mDataVersion, storedDevice->mDataVersionSize),
Span<const EmberAfDeviceType>(storedDevice->mDeviceTypeList,
storedDevice->mDeviceTypeListSize));

if (ret == EMBER_ZCL_STATUS_SUCCESS) {
LOG_INF("Added device to dynamic endpoint %d (index=%d)",
mCurrentDynamicEndpointId, index);
storedDevice->Init(mCurrentDynamicEndpointId);
return CHIP_NO_ERROR;
} else if (ret != EMBER_ZCL_STATUS_DUPLICATE_EXISTS) {
LOG_ERR("Failed to add dynamic endpoint: Internal error!");
RemoveBridgedDevice(mCurrentDynamicEndpointId); // TODO: check if this is ok, we
// need to cleanup the unused
// devices
return CHIP_ERROR_INTERNAL;
}
/* The adding algorithm differs depending on the devicesPairIndex value:
* - If devicesPairIndex has value it means that index and endpoint id are specified and should be assigned
* based on the input arguments (e.g. the device was loaded from storage and has to use specific data).
* - If devicesPairIndex has no value it means the default monotonically increasing numbering should be used.
*/
if (devicesPairIndex.HasValue()) {
index = devicesPairIndex.Value();

/* The requested index is already used. */
if (mDevicesMap.Contains(index)) {
return CHIP_ERROR_INTERNAL;
}

mDevicesMap.Insert(index, DevicePair(std::move(device), std::move(provider)));
err = CreateEndpoint(index, endpointId);

if (err == CHIP_NO_ERROR) {
devicesPairIndex.SetValue(index);
/* Make sure that the following endpoint id assignments will be monotonically continued from the
* biggest assigned number. */
mCurrentDynamicEndpointId =
mCurrentDynamicEndpointId > endpointId ? mCurrentDynamicEndpointId : endpointId;
}

return err;
} else {
while (index < kMaxBridgedDevices) {
/* Find the first empty index in the bridged devices list */
if (!mDevicesMap.Contains(index)) {
mDevicesMap.Insert(index, DevicePair(std::move(device), std::move(provider)));

/* Assign the free endpoint ID. */
do {
err = CreateEndpoint(index, endpointId);

/* Handle wrap condition */
if (++mCurrentDynamicEndpointId < mFirstDynamicEndpointId) {
mCurrentDynamicEndpointId = mFirstDynamicEndpointId;
}
} while (err == CHIP_ERROR_SENTINEL);

/* Handle wrap condition */
if (++mCurrentDynamicEndpointId < mFirstDynamicEndpointId) {
mCurrentDynamicEndpointId = mFirstDynamicEndpointId;
if (err == CHIP_NO_ERROR) {
devicesPairIndex.SetValue(index);
}

return err;
}
index++;
}
index++;
}

LOG_ERR("Failed to add dynamic endpoint: No endpoints available!");
Expand Down
13 changes: 10 additions & 3 deletions samples/matter/common/src/bridge/bridge_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
class BridgeManager {
public:
void Init();
CHIP_ERROR AddBridgedDevices(BridgedDevice *aDevice, BridgedDeviceDataProvider *aDataProvider);
CHIP_ERROR RemoveBridgedDevice(uint16_t endpoint);
CHIP_ERROR AddBridgedDevices(BridgedDevice *device, BridgedDeviceDataProvider *dataProvider,
uint8_t &devicesPairIndex);
CHIP_ERROR AddBridgedDevices(BridgedDevice *device, BridgedDeviceDataProvider *dataProvider,
uint8_t &devicesPairIndex, uint16_t endpointId);
CHIP_ERROR RemoveBridgedDevice(uint16_t endpoint, uint8_t &devicesPairIndex);
static CHIP_ERROR HandleRead(uint16_t index, chip::ClusterId clusterId,
const EmberAfAttributeMetadata *attributeMetadata, uint8_t *buffer,
uint16_t maxReadLength);
Expand Down Expand Up @@ -54,7 +57,11 @@ class BridgeManager {
};
using DeviceMap = FiniteMap<DevicePair, kMaxBridgedDevices>;

CHIP_ERROR AddDevices(BridgedDevice *aDevice, BridgedDeviceDataProvider *aDataProvider);
CHIP_ERROR AddBridgedDevices(BridgedDevice *device, BridgedDeviceDataProvider *dataProvider,
uint8_t &devicesPairIndex, uint16_t endpointId, chip::Optional<uint8_t> &index);
CHIP_ERROR AddDevices(BridgedDevice *aDevice, BridgedDeviceDataProvider *aDataProvider,
chip::Optional<uint8_t> &devicesPairIndex, uint16_t endpointId);
CHIP_ERROR CreateEndpoint(uint8_t index, uint16_t endpointId);

DeviceMap mDevicesMap;
uint16_t mNumberOfProviders{ 0 };
Expand Down

0 comments on commit c8e3d0e

Please sign in to comment.