Skip to content

Commit

Permalink
applications: Enabled using persistent storage in Matter bridge
Browse files Browse the repository at this point in the history
Added storing bridged devices in the persistent storage after
creation, removing them from the storage after removal and
loading them from the storage after boot.

Signed-off-by: Kamil Kasperczyk <kamil.kasperczyk@nordicsemi.no>
  • Loading branch information
kkasperczyk-no committed Aug 21, 2023
1 parent c8e3d0e commit b490959
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 30 deletions.
57 changes: 56 additions & 1 deletion applications/matter_bridge/src/app_task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "app_task.h"
#include "app_config.h"
#include "bridge_manager.h"
#include "bridge_storage_manager.h"
#include "bridged_devices_creator.h"
#include "led_util.h"

#ifdef CONFIG_BRIDGED_DEVICE_BT
Expand Down Expand Up @@ -149,7 +151,7 @@ CHIP_ERROR AppTask::Init()
PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));

/* Initialize bridge manager */
BridgeManager::Instance().Init();
BridgeManager::Instance().Init(RestoreBridgedDevices);

#ifdef CONFIG_BRIDGED_DEVICE_BT
BLEConnectivityManager::Instance().Init(sUuidServices, kUuidServicesNumber);
Expand Down Expand Up @@ -354,3 +356,56 @@ void AppTask::DispatchEvent(const AppEvent &event)
LOG_INF("Event received with no handler. Dropping event.");
}
}

CHIP_ERROR AppTask::RestoreBridgedDevices()
{
uint8_t count;
uint8_t indexes[BridgeManager::kMaxBridgedDevices] = { 0 };
size_t indexesCount = 0;

if (!BridgeStorageManager::Instance().LoadBridgedDevicesCount(count)) {
LOG_INF("No bridged devices to load from the storage.");
return CHIP_NO_ERROR;
}

if (!BridgeStorageManager::Instance().LoadBridgedDevicesIndexes(indexes, BridgeManager::kMaxBridgedDevices,
indexesCount)) {
return CHIP_ERROR_NOT_FOUND;
}

/* Load all devices based on the read count number. */
for (auto i = 0; i < static_cast<int>(indexesCount); i++) {
uint16_t endpointId;
char label[BridgedDevice::kNodeLabelSize] = { 0 };
size_t labelSize;
uint16_t deviceType;

if (!BridgeStorageManager::Instance().LoadBridgedDeviceEndpointId(endpointId, indexes[i])) {
return CHIP_ERROR_NOT_FOUND;
}

/* Ignore an error, as node label is optional, so it may not be found. */
BridgeStorageManager::Instance().LoadBridgedDeviceNodeLabel(label, sizeof(label), labelSize,
indexes[i]);

if (!BridgeStorageManager::Instance().LoadBridgedDeviceType(deviceType, indexes[i])) {
return CHIP_ERROR_NOT_FOUND;
}

#ifdef CONFIG_BRIDGED_DEVICE_BT
bt_addr_le_t addr;

if (!BridgeStorageManager::Instance().LoadBtAddress(addr, indexes[i])) {
return CHIP_ERROR_NOT_FOUND;
}

/* TODO: Add creating a device once BLE re-connection mechanism will be in place*/
#else
LOG_INF("Loaded bridged device on endpoint id %d from the storage", endpointId);

BridgedDeviceCreator::CreateDevice(deviceType, label, chip::Optional<uint8_t>(indexes[i]),
chip::Optional<uint16_t>(endpointId));
#endif
}
return CHIP_NO_ERROR;
}
1 change: 1 addition & 0 deletions applications/matter_bridge/src/app_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class AppTask {
static void LEDStateUpdateHandler(LEDWidget &ledWidget);
static void FunctionTimerTimeoutCallback(k_timer *timer);
static void UpdateStatusLED();
static CHIP_ERROR RestoreBridgedDevices();

FunctionEvent mFunction = FunctionEvent::NoneSelected;
bool mFunctionTimerActive = false;
Expand Down
169 changes: 159 additions & 10 deletions applications/matter_bridge/src/bridged_devices_creator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,70 @@ LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL);

namespace
{
CHIP_ERROR AddDevice(int deviceType, const char *nodeLabel, BridgedDeviceDataProvider *provider)
CHIP_ERROR StoreDevice(BridgedDevice *device, BridgedDeviceDataProvider *provider, uint8_t index)
{
uint16_t endpointId;
uint8_t count = 0;
uint8_t indexes[BridgeManager::kMaxBridgedDevices] = { 0 };
size_t indexesCount = 0;
bool deviceRefresh = false;

/* Check if a device is already present in the storage. */
if (BridgeStorageManager::Instance().LoadBridgedDeviceEndpointId(endpointId, index)) {
deviceRefresh = true;
}

if (!BridgeStorageManager::Instance().StoreBridgedDevice(device, index)) {
LOG_ERR("Failed to store bridged device");
return CHIP_ERROR_INTERNAL;
}

/* Store additional information that are not present for every generic BridgedDevice. */
#ifdef CONFIG_BRIDGED_DEVICE_BT
BLEBridgedDeviceProvider *bleProvider = static_cast<BLEBridgedDeviceProvider *>(provider);

bt_addr_le_t addr;
if (!bleProvider->GetBtAddress(&addr)) {
return CHIP_ERROR_INTERNAL;
}

if (!BridgeStorageManager::Instance().StoreBtAddress(addr, index)) {
LOG_ERR("Failed to store bridged device's Bluetooth address");
return CHIP_ERROR_INTERNAL;
}
#endif

/* If a device was not present in the storage before, put new index on the end of list and increment the count
* number of stored devices. */
if (!deviceRefresh) {
BridgeStorageManager::Instance().LoadBridgedDevicesIndexes(indexes, BridgeManager::kMaxBridgedDevices,
indexesCount);

if (indexesCount >= BridgeManager::kMaxBridgedDevices) {
return CHIP_ERROR_BUFFER_TOO_SMALL;
}

indexes[indexesCount] = index;
indexesCount++;

if (!BridgeStorageManager::Instance().StoreBridgedDevicesIndexes(indexes, indexesCount)) {
LOG_ERR("Failed to store bridged devices indexes.");
return CHIP_ERROR_INTERNAL;
}

BridgeStorageManager::Instance().LoadBridgedDevicesCount(count);

if (!BridgeStorageManager::Instance().StoreBridgedDevicesCount(count + 1)) {
LOG_ERR("Failed to store bridged devices count.");
return CHIP_ERROR_INTERNAL;
}
}

return CHIP_NO_ERROR;
}

CHIP_ERROR AddDevice(int deviceType, const char *nodeLabel, BridgedDeviceDataProvider *provider,
chip::Optional<uint8_t> index, chip::Optional<uint16_t> endpointId)
{
VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INVALID_ARGUMENT,
LOG_ERR("Cannot allocate data provider of given type"));
Expand All @@ -29,10 +92,19 @@ CHIP_ERROR AddDevice(int deviceType, const char *nodeLabel, BridgedDeviceDataPro
return CHIP_ERROR_INTERNAL;
}

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

if (index.HasValue() && endpointId.HasValue()) {
deviceIndex = index.Value();
err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevice, provider, deviceIndex,
endpointId.Value());
} else {
err = BridgeManager::Instance().AddBridgedDevices(newBridgedDevice, provider, deviceIndex);
}

if (err == CHIP_NO_ERROR) {
err = StoreDevice(newBridgedDevice, provider, deviceIndex);
} else if (err == CHIP_ERROR_INVALID_STRING_LENGTH) {
LOG_ERR("Error: too long node label (max %d)", BridgedDevice::kNodeLabelSize);
} else if (err == CHIP_ERROR_NO_MEMORY) {
Expand All @@ -59,6 +131,8 @@ struct BluetoothConnectionContext {
int deviceType;
char nodeLabel[BridgedDevice::kNodeLabelSize];
BLEBridgedDeviceProvider *provider;
chip::Optional<uint8_t> index;
chip::Optional<uint16_t> endpointId;
};

void BluetoothDeviceConnected(BLEBridgedDevice *device, bt_gatt_dm *discoveredData, bool discoverySucceeded,
Expand All @@ -76,11 +150,12 @@ void BluetoothDeviceConnected(BLEBridgedDevice *device, bt_gatt_dm *discoveredDa
return;
}

AddDevice(ctx->deviceType, ctx->nodeLabel, ctx->provider);
AddDevice(ctx->deviceType, ctx->nodeLabel, ctx->provider, ctx->index, ctx->endpointId);
}
}

BridgedDeviceDataProvider *CreateBleProvider(int deviceType, const char *nodeLabel, int bleDeviceIndex)
BridgedDeviceDataProvider *CreateBleProvider(int deviceType, const char *nodeLabel, int bleDeviceIndex,
chip::Optional<uint8_t> index, chip::Optional<uint16_t> endpointId)
{
/* The device object can be created once the Bluetooth LE connection will be established. */
BluetoothConnectionContext *context = chip::Platform::New<BluetoothConnectionContext>();
Expand All @@ -104,6 +179,8 @@ BridgedDeviceDataProvider *CreateBleProvider(int deviceType, const char *nodeLab
}

contextPtr->provider = static_cast<BLEBridgedDeviceProvider *>(provider);
contextPtr->index = index;
contextPtr->endpointId = endpointId;

CHIP_ERROR err = BLEConnectivityManager::Instance().Connect(
bleDeviceIndex, BluetoothDeviceConnected, contextPtr.get(), contextPtr->provider->GetServiceUuid());
Expand All @@ -122,13 +199,14 @@ CHIP_ERROR BridgedDeviceCreator::CreateDevice(int deviceType, const char *nodeLa
,
int bleDeviceIndex
#endif
)
,
chip::Optional<uint8_t> index, chip::Optional<uint16_t> endpointId)
{
BridgedDeviceDataProvider *provider = nullptr;

#if defined(CONFIG_BRIDGED_DEVICE_BT)
/* The device cannot be created in line, it has to wait for connected callback. */
provider = CreateBleProvider(deviceType, nodeLabel, bleDeviceIndex);
provider = CreateBleProvider(deviceType, nodeLabel, bleDeviceIndex, index, endpointId);

if (!provider) {
return CHIP_ERROR_INTERNAL;
Expand All @@ -137,15 +215,86 @@ CHIP_ERROR BridgedDeviceCreator::CreateDevice(int deviceType, const char *nodeLa
#elif defined(CONFIG_BRIDGED_DEVICE_SIMULATED)
provider = CreateSimulatedProvider(deviceType);
/* The device is simulated, so it can be added immediately. */
return AddDevice(deviceType, nodeLabel, provider);
return AddDevice(deviceType, nodeLabel, provider, index, endpointId);
#else
return CHIP_ERROR_NOT_IMPLEMENTED;
#endif

return CHIP_NO_ERROR;
}

CHIP_ERROR BridgedDeviceCreator::RemoveDevice(int endpointId)
{
uint8_t index = 0;
uint8_t index;
uint8_t count = 0;
uint8_t indexes[BridgeManager::kMaxBridgedDevices] = { 0 };
size_t indexesCount = 0;
CHIP_ERROR err = BridgeManager::Instance().RemoveBridgedDevice(endpointId, index);

if (CHIP_NO_ERROR != err) {
LOG_ERR("Failed to remove bridged device");
return err;
}

if (!BridgeStorageManager::Instance().LoadBridgedDevicesIndexes(indexes, BridgeManager::kMaxBridgedDevices,
indexesCount)) {
LOG_ERR("Failed to load stored bridged device indexes");
return CHIP_ERROR_INTERNAL;
}

/* Find the required index on the list, remove it and move all following indexes one position earlier. */
bool indexFound = false;
for (auto i = 0; i < static_cast<int>(indexesCount); i++) {
if (indexes[i] == index) {
indexFound = true;
}

if (indexFound && ((i + 1) < BridgeManager::kMaxBridgedDevices)) {
indexes[i] = indexes[i + 1];
}
}

if (indexFound) {
indexesCount--;
} else {
return CHIP_ERROR_NOT_FOUND;
}

/* Update the current indexes list. */
if (!BridgeStorageManager::Instance().StoreBridgedDevicesIndexes(indexes, indexesCount)) {
LOG_ERR("Failed to store bridged devices indexes.");
return CHIP_ERROR_INTERNAL;
}

if (!BridgeStorageManager::Instance().LoadBridgedDevicesCount(count)) {
LOG_ERR("Failed to load bridged devices count.");
return CHIP_ERROR_INTERNAL;
}

if (!BridgeStorageManager::Instance().StoreBridgedDevicesCount(count - 1)) {
LOG_ERR("Failed to store bridged devices count.");
return CHIP_ERROR_INTERNAL;
}

if (!BridgeStorageManager::Instance().RemoveBridgedDeviceEndpointId(index)) {
LOG_ERR("Failed to remove bridged device endpoint id.");
return CHIP_ERROR_INTERNAL;
}

/* Ignore error, as node label may not be present in the storage. */
BridgeStorageManager::Instance().RemoveBridgedDeviceNodeLabel(index);

if (!BridgeStorageManager::Instance().RemoveBridgedDeviceType(index)) {
LOG_ERR("Failed to remove bridged device type.");
return CHIP_ERROR_INTERNAL;
}

#ifdef CONFIG_BRIDGED_DEVICE_BT
if (!BridgeStorageManager::Instance().RemoveBtAddress(index)) {
LOG_ERR("Failed to remove bridged device Bluetooth address.");
return CHIP_ERROR_INTERNAL;
}
#endif

return BridgeManager::Instance().RemoveBridgedDevice(endpointId, index);
return CHIP_NO_ERROR;
}
28 changes: 27 additions & 1 deletion applications/matter_bridge/src/bridged_devices_creator.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,40 @@
#pragma once

#include <lib/core/CHIPError.h>
#include <lib/core/Optional.h>

namespace BridgedDeviceCreator
{
/**
* @brief Create a bridged device.
*
* @param deviceType the Matter device type of a bridged device to be created
* @param nodeLabel node label of a Matter device to be created
* @param bleDeviceIndex index of Bluetooth LE device on the scanned devices list to be bridged with Matter bridged
* device
* @param index optional index object that shall have a valid value set if the value is meant
* to be used to index assignment, or shall not have a value set if the default index assignment should be used.
* @param endpointId optional endpoint id object that shall have a valid value set if the value is meant
* to be used to endpoint id assignment, or shall not have a value set if the default endpoint id assignment should be
* used.
* @return CHIP_NO_ERROR on success
* @return other error code on failure
*/
CHIP_ERROR CreateDevice(int deviceType, const char *nodeLabel
#ifdef CONFIG_BRIDGED_DEVICE_BT
,
int bleDeviceIndex
#endif
);
,
chip::Optional<uint8_t> index = chip::Optional<uint8_t>(),
chip::Optional<uint16_t> endpointId = chip::Optional<uint16_t>());

/**
* @brief Remove bridged device.
*
* @param endpoint value of endpoint id specifying the bridged device to be removed
* @return CHIP_NO_ERROR on success
* @return other error code on failure
*/
CHIP_ERROR RemoveDevice(int endpointId);
} /* namespace BridgedDeviceCreator */
Loading

0 comments on commit b490959

Please sign in to comment.