Skip to content

Commit

Permalink
[Fabric-Bridge] Refactor device management from main (#33618)
Browse files Browse the repository at this point in the history
* [Fabric-Bridge] Refactor device management from main

* Address review comments
  • Loading branch information
yufengwangca authored May 31, 2024
1 parent 55012bf commit b3fc1d0
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 211 deletions.
2 changes: 2 additions & 0 deletions examples/fabric-bridge-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ executable("fabric-bridge-app") {
sources = [
"${chip_root}/examples/fabric-bridge-app/fabric-bridge-common/include/CHIPProjectAppConfig.h",
"Device.cpp",
"DeviceManager.cpp",
"include/Device.h",
"include/DeviceManager.h",
"main.cpp",
]

Expand Down
6 changes: 3 additions & 3 deletions examples/fabric-bridge-app/linux/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ void Device::SetReachable(bool aReachable)

if (aReachable)
{
ChipLogProgress(DeviceLayer, "Device[%s]: ONLINE", mName);
ChipLogProgress(NotSpecified, "Device[%s]: ONLINE", mName);
}
else
{
ChipLogProgress(DeviceLayer, "Device[%s]: OFFLINE", mName);
ChipLogProgress(NotSpecified, "Device[%s]: OFFLINE", mName);
}

if (changed)
Expand All @@ -63,7 +63,7 @@ void Device::SetName(const char * szName)
{
bool changed = (strncmp(mName, szName, sizeof(mName)) != 0);

ChipLogProgress(DeviceLayer, "Device[%s]: New Name=\"%s\"", mName, szName);
ChipLogProgress(NotSpecified, "Device[%s]: New Name=\"%s\"", mName, szName);

chip::Platform::CopyString(mName, szName);

Expand Down
130 changes: 130 additions & 0 deletions examples/fabric-bridge-app/linux/DeviceManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
*
* 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

DeviceManager::DeviceManager()
{
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;
}
68 changes: 68 additions & 0 deletions examples/fabric-bridge-app/linux/include/DeviceManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
*
* 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.
*/

#pragma once

#include <platform/CHIPDeviceLayer.h>

#include "Device.h"

class DeviceManager
{
public:
DeviceManager();

/**
* @brief Adds a device to a dynamic endpoint.
*
* This function attempts to add a device to a dynamic endpoint. It tries to find an available
* endpoint slot and retries the addition process up to a specified maximum number of times if
* the endpoint already exists. If the addition is successful, it returns the index of the
* dynamic endpoint; otherwise, it returns -1.
*
* @param dev A pointer to the device to be added.
* @param ep A pointer to the endpoint type.
* @param deviceTypeList A span containing the list of device types.
* @param dataVersionStorage A span containing the data version storage.
* @param parentEndpointId The parent endpoint ID. Defaults to an invalid endpoint ID.
* @return int The index of the dynamic endpoint if successful, -1 otherwise.
*/
int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const chip::Span<const EmberAfDeviceType> & deviceTypeList,
const chip::Span<chip::DataVersion> & dataVersionStorage,
chip::EndpointId parentEndpointId = chip::kInvalidEndpointId);

/**
* @brief Removes a device from a dynamic endpoint.
*
* This function attempts to remove a device from a dynamic endpoint by iterating through the
* available endpoints and checking if the device matches. If the device is found, it clears the
* dynamic endpoint, logs the removal, and returns the index of the removed endpoint.
* If the device is not found, it returns -1.
*
* @param dev A pointer to the device to be removed.
* @return int The index of the removed dynamic endpoint if successful, -1 otherwise.
*/
int RemoveDeviceEndpoint(Device * dev);

Device * GetDevice(uint16_t index) const;

private:
chip::EndpointId mCurrentEndpointId;
chip::EndpointId mFirstDynamicEndpointId;
Device * mDevices[CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT + 1];
};
Loading

0 comments on commit b3fc1d0

Please sign in to comment.