diff --git a/applications/matter_bridge/CMakeLists.txt b/applications/matter_bridge/CMakeLists.txt index 1b92824d75a..f374bb7b803 100644 --- a/applications/matter_bridge/CMakeLists.txt +++ b/applications/matter_bridge/CMakeLists.txt @@ -46,6 +46,7 @@ target_sources(app PRIVATE ${COMMON_ROOT}/src/bridge/bridge_manager.cpp ${COMMON_ROOT}/src/bridge/bridged_device.cpp ${COMMON_ROOT}/src/bridge/bridge_storage_manager.cpp + ${COMMON_ROOT}/src/bridge/bridged_device_data_provider.cpp src/zap-generated/IMClusterCommandHandler.cpp src/zap-generated/callback-stub.cpp ${COMMON_ROOT}/src/led_widget.cpp diff --git a/applications/matter_bridge/src/bridged_device_types/ble_onoff_light_data_provider.cpp b/applications/matter_bridge/src/bridged_device_types/ble_onoff_light_data_provider.cpp index d574fe1903c..a51e9268896 100644 --- a/applications/matter_bridge/src/bridged_device_types/ble_onoff_light_data_provider.cpp +++ b/applications/matter_bridge/src/bridged_device_types/ble_onoff_light_data_provider.cpp @@ -60,8 +60,7 @@ void BleOnOffLightDataProvider::NotifyUpdateState(chip::ClusterId clusterId, chi size_t dataSize) { if (mUpdateAttributeCallback) { - mUpdateAttributeCallback(*this, Clusters::OnOff::Id, Clusters::OnOff::Attributes::OnOff::Id, data, - dataSize); + mUpdateAttributeCallback(*this, clusterId, attributeId, data, dataSize); } } diff --git a/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp b/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp index d02a34ce3e7..c03f1cc36ac 100644 --- a/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp +++ b/applications/matter_bridge/src/bridged_device_types/onoff_light.cpp @@ -112,28 +112,37 @@ CHIP_ERROR OnOffLightDevice::HandleWrite(ClusterId clusterId, AttributeId attrib CHIP_ERROR OnOffLightDevice::HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) { - if (clusterId != Clusters::OnOff::Id || !data) { + if (!data) { return CHIP_ERROR_INVALID_ARGUMENT; } - CHIP_ERROR err; + switch (clusterId) { + case Clusters::BridgedDeviceBasicInformation::Id: + HandleWriteDeviceBasicInformation(clusterId, attributeId, data, dataSize); + return CHIP_NO_ERROR; + case Clusters::OnOff::Id: { + switch (attributeId) { + case Clusters::OnOff::Attributes::OnOff::Id: { + CHIP_ERROR err; - switch (attributeId) { - case Clusters::OnOff::Attributes::OnOff::Id: { - bool value; + bool value; - err = CopyAttribute(data, dataSize, &value, sizeof(value)); + err = CopyAttribute(data, dataSize, &value, sizeof(value)); - if (err != CHIP_NO_ERROR) { - return err; - } + if (err != CHIP_NO_ERROR) { + return err; + } - SetOnOff(value); - break; + SetOnOff(value); + break; + } + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } } default: return CHIP_ERROR_INVALID_ARGUMENT; } - return err; + return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/samples/matter/common/src/bridge/Kconfig b/samples/matter/common/src/bridge/Kconfig index 78c4ab4fe96..c1ac68088b1 100644 --- a/samples/matter/common/src/bridge/Kconfig +++ b/samples/matter/common/src/bridge/Kconfig @@ -11,3 +11,15 @@ config BRIDGE_MAX_DYNAMIC_ENDPOINTS_NUMBER config BRIDGE_MAX_BRIDGED_DEVICES_NUMBER int "Maximum number of physical non-Matter devices supported by the Bridge" default 16 + +if BRIDGED_DEVICE_BT + +config BRIDGE_BT_RECOVERY_INTERVAL_MS + int "Time (in ms) between recovery attempts when the BLE connection to the bridged device is lost" + default 1000 + +config BRIDGE_BT_RECOVERY_SCAN_TIMEOUT_MS + int "Time (in ms) within which the Bridge will try to re-establish a connection to the lost BT LE device" + default 2000 + +endif diff --git a/samples/matter/common/src/bridge/ble_bridged_device.h b/samples/matter/common/src/bridge/ble_bridged_device.h index 0f3e56bfd5e..d02543f8a37 100644 --- a/samples/matter/common/src/bridge/ble_bridged_device.h +++ b/samples/matter/common/src/bridge/ble_bridged_device.h @@ -33,8 +33,8 @@ struct BLEBridgedDevice { bool discoverySucceeded, void *context); bt_addr_le_t mAddr; - DeviceConnectedCallback mConnectedCallback; - void *mConnectedCallbackContext; + DeviceConnectedCallback mFirstConnectionCallback; + void *mFirstConnectionCallbackContext; bt_uuid *mServiceUuid; bt_conn *mConn; BLEBridgedDeviceProvider *mProvider; diff --git a/samples/matter/common/src/bridge/ble_connectivity_manager.cpp b/samples/matter/common/src/bridge/ble_connectivity_manager.cpp index fdab1f7da1f..3a1bb95fb3e 100644 --- a/samples/matter/common/src/bridge/ble_connectivity_manager.cpp +++ b/samples/matter/common/src/bridge/ble_connectivity_manager.cpp @@ -68,8 +68,8 @@ void BLEConnectivityManager::ConnectionHandler(bt_conn *conn, uint8_t conn_err) /* Find the created device instance based on address. */ for (int i = 0; i < Instance().mCreatedDevicesCounter; i++) { - if (memcmp(&Instance().mCreatedDevices[i].mAddr, addr, - sizeof(Instance().mCreatedDevices[i].mAddr)) == 0) { + if (memcmp(&Instance().mCreatedDevices[i].mAddr, addr, sizeof(Instance().mCreatedDevices[i].mAddr)) == + 0) { device = &Instance().mCreatedDevices[i]; break; } @@ -79,10 +79,15 @@ void BLEConnectivityManager::ConnectionHandler(bt_conn *conn, uint8_t conn_err) return; } - LOG_INF("Connected: %s", str_addr); - /* TODO: Add security validation. */ + if (conn_err && Instance().mRecovery.mRecoveryInProgress) { + Instance().mRecovery.PutDevice(device); + return; + } + + LOG_INF("Connected: %s", str_addr); + /* Start GATT discovery for the device's service UUID. */ err = bt_gatt_dm_start(conn, device->mServiceUuid, &discovery_cb, device); if (err) { @@ -94,19 +99,35 @@ void BLEConnectivityManager::ConnectionHandler(bt_conn *conn, uint8_t conn_err) void BLEConnectivityManager::DisconnectionHandler(bt_conn *conn, uint8_t reason) { - char addr[BT_ADDR_LE_STR_LEN]; + /* Verify whether the device should be recovered */ + BLEBridgedDevice *device = Instance().FindBLEBridgedDevice(conn); - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + if (device) { + char addr[BT_ADDR_LE_STR_LEN]; + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - LOG_INF("Disconnected: %s (reason %u)", addr, reason); + LOG_INF("Disconnected: %s (reason %u)", addr, reason); - /* TODO: Implement connection re-establishment procedure. */ + if (device->mConn) { + bt_conn_unref(device->mConn); + device->mConn = nullptr; + } + + if (reason == BT_HCI_ERR_CONN_TIMEOUT) { + Instance().mRecovery.NotifyLostDevice(device); + if (device->mProvider) { + VerifyOrReturn(CHIP_NO_ERROR == device->mProvider->NotifyReachableStatusChange(false), + LOG_WRN("The device has not been notified about the status change.")); + } + } + + /* TODO Add removing a device when disconnection has been invoked by the user */ + } } void BLEConnectivityManager::DiscoveryCompletedHandler(bt_gatt_dm *dm, void *context) { LOG_INF("The GATT discovery completed"); - BLEBridgedDevice *device = reinterpret_cast(context); bool discoveryResult = false; const bt_gatt_dm_attr *gatt_service_attr = bt_gatt_dm_service_get(dm); @@ -120,7 +141,22 @@ void BLEConnectivityManager::DiscoveryCompletedHandler(bt_gatt_dm *dm, void *con discoveryResult = true; exit: - device->mConnectedCallback(device, dm, discoveryResult, device->mConnectedCallbackContext); + if (!Instance().mRecovery.mRecoveryInProgress) { + device->mFirstConnectionCallback(device, dm, discoveryResult, device->mFirstConnectionCallbackContext); + } + + if (device->mProvider) { + VerifyOrReturn(CHIP_NO_ERROR == device->mProvider->NotifyReachableStatusChange(true), + LOG_WRN("The device has not been notified about the status change.")); + } + + Instance().mRecovery.mRecoveryInProgress = false; + + if (Instance().mRecovery.IsNeeded()) { + Instance().mRecovery.StartTimer(); + } + + bt_gatt_dm_data_release(dm); } void BLEConnectivityManager::DiscoveryNotFound(bt_conn *conn, void *context) @@ -129,7 +165,7 @@ void BLEConnectivityManager::DiscoveryNotFound(bt_conn *conn, void *context) BLEBridgedDevice *device = reinterpret_cast(context); - device->mConnectedCallback(device, nullptr, false, device->mConnectedCallbackContext); + device->mFirstConnectionCallback(device, nullptr, false, device->mFirstConnectionCallbackContext); } void BLEConnectivityManager::DiscoveryError(bt_conn *conn, int err, void *context) @@ -138,7 +174,7 @@ void BLEConnectivityManager::DiscoveryError(bt_conn *conn, int err, void *contex BLEBridgedDevice *device = reinterpret_cast(context); - device->mConnectedCallback(device, nullptr, false, device->mConnectedCallbackContext); + device->mFirstConnectionCallback(device, nullptr, false, device->mFirstConnectionCallbackContext); } CHIP_ERROR BLEConnectivityManager::Init(bt_uuid **serviceUuids, uint8_t serviceUuidsCount) @@ -180,7 +216,7 @@ CHIP_ERROR BLEConnectivityManager::Init(bt_uuid **serviceUuids, uint8_t serviceU return CHIP_NO_ERROR; } -CHIP_ERROR BLEConnectivityManager::Scan(ScanDoneCallback callback, void *context) +CHIP_ERROR BLEConnectivityManager::Scan(ScanDoneCallback callback, void *context, uint32_t scanTimeoutMs) { if (mScanActive) { LOG_ERR("Scan is already in progress"); @@ -201,12 +237,43 @@ CHIP_ERROR BLEConnectivityManager::Scan(ScanDoneCallback callback, void *context return System::MapErrorZephyr(err); } - k_timer_start(&mScanTimer, K_MSEC(kScanTimeoutMs), K_NO_WAIT); + k_timer_start(&mScanTimer, K_MSEC(scanTimeoutMs), K_NO_WAIT); mScanActive = true; return CHIP_NO_ERROR; } +void BLEConnectivityManager::ReScanCallback(ScannedDevice *devices, uint8_t count, void *context) +{ + LOG_DBG("Lost devices no. %d", Instance().mRecovery.GetCurrentAmount()); + LOG_DBG("Found devices no. %d", Instance().mScannedDevicesCounter); + + if (Instance().mScannedDevicesCounter != 0 && !Instance().mRecovery.mRecoveryInProgress) { + BLEBridgedDevice *deviceLost = Instance().mRecovery.GetDevice(); + if (deviceLost) { + for (uint8_t idx = 0; idx < Instance().mScannedDevicesCounter; idx++) { + auto &deviceScanned = Instance().mScannedDevices[idx]; + if (memcmp(&deviceScanned.mAddr, &deviceLost->mAddr, sizeof(deviceLost->mAddr)) == 0) { + LOG_DBG("Found the lost device"); + + Instance().mRecovery.mIndexToRecover = idx; + Instance().mRecovery.mCurrentDevice = deviceLost; + Instance().mRecovery.mRecoveryInProgress = true; + + DeviceLayer::PlatformMgr().ScheduleWork( + [](intptr_t context) { Instance().Reconnect(); }, 0); + break; + } + } + if (!Instance().mRecovery.mRecoveryInProgress) { + Instance().mRecovery.NotifyLostDevice(deviceLost); + } + } + } else if (Instance().mRecovery.IsNeeded()) { + Instance().mRecovery.StartTimer(); + } +} + CHIP_ERROR BLEConnectivityManager::StopScan() { if (!mScanActive) { @@ -232,9 +299,25 @@ void BLEConnectivityManager::ScanTimeoutCallback(k_timer *timer) void BLEConnectivityManager::ScanTimeoutHandle(intptr_t context) { Instance().StopScan(); - Instance().mScanDoneCallback(Instance().mScannedDevices, - Instance().mScannedDevicesCounter, - Instance().mScanDoneCallbackContext); + Instance().mScanDoneCallback(Instance().mScannedDevices, Instance().mScannedDevicesCounter, + Instance().mScanDoneCallbackContext); +} + +CHIP_ERROR BLEConnectivityManager::Reconnect() +{ + StopScan(); + + bt_conn *conn; + + int err = bt_conn_le_create(&mScannedDevices[Instance().mRecovery.mIndexToRecover].mAddr, create_param, + &mScannedDevices[Instance().mRecovery.mIndexToRecover].mConnParam, &conn); + + if (err) { + LOG_ERR("Creating reconnection failed (err %d)", err); + return System::MapErrorZephyr(err); + } + + return CHIP_NO_ERROR; } CHIP_ERROR BLEConnectivityManager::Connect(uint8_t index, BLEBridgedDevice::DeviceConnectedCallback callback, @@ -267,8 +350,8 @@ CHIP_ERROR BLEConnectivityManager::Connect(uint8_t index, BLEBridgedDevice::Devi } mCreatedDevices[mCreatedDevicesCounter].mAddr = mScannedDevices[index].mAddr; - mCreatedDevices[mCreatedDevicesCounter].mConnectedCallback = callback; - mCreatedDevices[mCreatedDevicesCounter].mConnectedCallbackContext = context; + mCreatedDevices[mCreatedDevicesCounter].mFirstConnectionCallback = callback; + mCreatedDevices[mCreatedDevicesCounter].mFirstConnectionCallbackContext = context; mCreatedDevices[mCreatedDevicesCounter].mServiceUuid = serviceUuid; mCreatedDevicesCounter++; @@ -295,3 +378,42 @@ BLEBridgedDevice *BLEConnectivityManager::FindBLEBridgedDevice(bt_conn *conn) return nullptr; } + +BLEConnectivityManager::Recovery::Recovery() +{ + ring_buf_init(&mRingBuf, sizeof(mDevicesToRecover), reinterpret_cast(mDevicesToRecover)); + k_timer_init(&mRecoveryTimer, TimerTimeoutCallback, nullptr); + k_timer_user_data_set(&mRecoveryTimer, this); +} + +void BLEConnectivityManager::Recovery::NotifyLostDevice(BLEBridgedDevice *device) +{ + if (device) { + PutDevice(device); + StartTimer(); + } +} + +void BLEConnectivityManager::Recovery::TimerTimeoutCallback(k_timer *timer) +{ + LOG_DBG("Re-scanning BLE connections..."); + DeviceLayer::PlatformMgr().ScheduleWork( + [](intptr_t) { Instance().Scan(ReScanCallback, nullptr, kRecoveryScanTimeoutMs); }, 0); +} + +BLEBridgedDevice *BLEConnectivityManager::Recovery::GetDevice() +{ + uint32_t deviceAddr; + int ret = ring_buf_get(&mRingBuf, reinterpret_cast(&deviceAddr), sizeof(deviceAddr)); + if (ret == sizeof(deviceAddr)) { + return reinterpret_cast(deviceAddr); + } + + return nullptr; +} + +bool BLEConnectivityManager::Recovery::PutDevice(BLEBridgedDevice *device) +{ + int ret = ring_buf_put(&mRingBuf, reinterpret_cast(&device), sizeof(device)); + return ret == sizeof(device); +} diff --git a/samples/matter/common/src/bridge/ble_connectivity_manager.h b/samples/matter/common/src/bridge/ble_connectivity_manager.h index 550d64abd3a..4cd47a05e20 100644 --- a/samples/matter/common/src/bridge/ble_connectivity_manager.h +++ b/samples/matter/common/src/bridge/ble_connectivity_manager.h @@ -14,8 +14,45 @@ #include #include #include +#include class BLEConnectivityManager { +public: + static constexpr uint16_t kScanTimeoutMs = 10000; + static constexpr uint16_t kMaxScannedDevices = 16; + /* One BT connection is reserved for the Matter service purposes. */ + static constexpr uint16_t kMaxCreatedDevices = CONFIG_BT_MAX_CONN - 1; + static constexpr uint8_t kMaxServiceUuids = CONFIG_BT_SCAN_UUID_CNT; + +private: + class Recovery { + friend class BLEConnectivityManager; + constexpr static auto kRecoveryIntervalMs = CONFIG_BRIDGE_BT_RECOVERY_INTERVAL_MS; + constexpr static auto kRecoveryScanTimeoutMs = CONFIG_BRIDGE_BT_RECOVERY_SCAN_TIMEOUT_MS; + + public: + Recovery(); + ~Recovery() { CancelTimer(); } + void NotifyLostDevice(BLEBridgedDevice *device); + + private: + BLEBridgedDevice *GetDevice(); + bool PutDevice(BLEBridgedDevice *device); + bool IsNeeded() { return !ring_buf_is_empty(&mRingBuf); } + void StartTimer() { k_timer_start(&mRecoveryTimer, K_MSEC(kRecoveryIntervalMs), K_NO_WAIT); } + void CancelTimer() { k_timer_stop(&mRecoveryTimer); } + size_t GetCurrentAmount() { return ring_buf_size_get(&mRingBuf) / sizeof(BLEBridgedDevice *); } + + static void TimerTimeoutCallback(k_timer *timer); + + BLEBridgedDevice *mDevicesToRecover[BLEConnectivityManager::kMaxCreatedDevices]; + BLEBridgedDevice *mCurrentDevice = nullptr; + bool mRecoveryInProgress = false; + ring_buf mRingBuf; + uint8_t mIndexToRecover; + k_timer mRecoveryTimer; + }; + public: struct ScannedDevice { bt_addr_le_t mAddr; @@ -24,17 +61,12 @@ class BLEConnectivityManager { using ScanDoneCallback = void (*)(ScannedDevice *devices, uint8_t count, void *context); - static constexpr uint16_t kScanTimeoutMs = 10000; - static constexpr uint16_t kMaxScannedDevices = 16; - /* One BT connection is reserved for the Matter service purposes. */ - static constexpr uint16_t kMaxCreatedDevices = CONFIG_BT_MAX_CONN - 1; - static constexpr uint8_t kMaxServiceUuids = CONFIG_BT_SCAN_UUID_CNT; - CHIP_ERROR Init(bt_uuid **serviceUuids, uint8_t serviceUuidsCount); - CHIP_ERROR Scan(ScanDoneCallback callback, void *context); + CHIP_ERROR Scan(ScanDoneCallback callback, void *context, uint32_t scanTimeoutMs = kScanTimeoutMs); CHIP_ERROR StopScan(); CHIP_ERROR Connect(uint8_t index, BLEBridgedDevice::DeviceConnectedCallback callback, void *context, bt_uuid *serviceUuid); + CHIP_ERROR Reconnect(); BLEBridgedDevice *FindBLEBridgedDevice(bt_conn *conn); static void FilterMatch(bt_scan_device_info *device_info, bt_scan_filter_match *filter_match, bool connectable); @@ -46,11 +78,12 @@ class BLEConnectivityManager { static void DiscoveryNotFound(bt_conn *conn, void *context); static void DiscoveryError(bt_conn *conn, int err, void *context); - static BLEConnectivityManager & Instance() - { - static BLEConnectivityManager sInstance; - return sInstance; - } + static BLEConnectivityManager &Instance() + { + static BLEConnectivityManager sInstance; + return sInstance; + } + static void ReScanCallback(ScannedDevice *devices, uint8_t count, void *context); private: bool mScanActive; @@ -63,4 +96,5 @@ class BLEConnectivityManager { uint8_t mServicesUuidCount; ScanDoneCallback mScanDoneCallback; void *mScanDoneCallbackContext; + Recovery mRecovery; }; diff --git a/samples/matter/common/src/bridge/bridged_device.cpp b/samples/matter/common/src/bridge/bridged_device.cpp index 7bab12ba28e..7a20cc6d10b 100644 --- a/samples/matter/common/src/bridge/bridged_device.cpp +++ b/samples/matter/common/src/bridge/bridged_device.cpp @@ -10,8 +10,7 @@ using namespace ::chip; using namespace ::chip::app; -CHIP_ERROR BridgedDevice::CopyAttribute(void *attribute, size_t attributeSize, void *buffer, - uint16_t maxBufferSize) +CHIP_ERROR BridgedDevice::CopyAttribute(void *attribute, size_t attributeSize, void *buffer, uint16_t maxBufferSize) { if (maxBufferSize < attributeSize) { return CHIP_ERROR_INVALID_ARGUMENT; @@ -22,6 +21,20 @@ CHIP_ERROR BridgedDevice::CopyAttribute(void *attribute, size_t attributeSize, v return CHIP_NO_ERROR; } +CHIP_ERROR BridgedDevice::HandleWriteDeviceBasicInformation(chip::ClusterId clusterId, chip::AttributeId attributeId, + void *data, size_t dataSize) +{ + switch (attributeId) { + case Clusters::BridgedDeviceBasicInformation::Attributes::Reachable::Id: + if (data && dataSize == sizeof(bool)) { + SetIsReachable(*reinterpret_cast(data)); + return CHIP_NO_ERROR; + } + default: + return CHIP_ERROR_INVALID_ARGUMENT; + } +} + CHIP_ERROR BridgedDevice::HandleReadBridgedDeviceBasicInformation(AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength) { diff --git a/samples/matter/common/src/bridge/bridged_device.h b/samples/matter/common/src/bridge/bridged_device.h index 4cafd481373..0fcee5c26cf 100644 --- a/samples/matter/common/src/bridge/bridged_device.h +++ b/samples/matter/common/src/bridge/bridged_device.h @@ -67,12 +67,15 @@ class BridgedDevice { virtual CHIP_ERROR HandleAttributeChange(chip::ClusterId clusterId, chip::AttributeId attributeId, void *data, size_t dataSize) = 0; CHIP_ERROR CopyAttribute(void *attribute, size_t attributeSize, void *buffer, uint16_t maxBufferSize); + CHIP_ERROR HandleWriteDeviceBasicInformation(chip::ClusterId clusterId, chip::AttributeId attributeId, + void *data, size_t dataSize); CHIP_ERROR HandleReadBridgedDeviceBasicInformation(chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength); CHIP_ERROR HandleReadDescriptor(chip::AttributeId attributeId, uint8_t *buffer, uint16_t maxReadLength); bool GetIsReachable() const { return mIsReachable; } const char *GetNodeLabel() const { return mNodeLabel; } + void SetIsReachable(bool isReachable) { mIsReachable = isReachable; } uint16_t GetBridgedDeviceBasicInformationClusterRevision() { return kBridgedDeviceBasicInformationClusterRevision; @@ -81,6 +84,8 @@ class BridgedDevice { uint16_t GetDescriptorClusterRevision() { return kDescriptorClusterRevision; } uint32_t GetDescriptorFeatureMap() { return kDescrtiptorFeatureMap; } + static void NotifyAttributeChange(intptr_t context); + EmberAfEndpointType *mEp; const EmberAfDeviceType *mDeviceTypeList; size_t mDeviceTypeListSize; diff --git a/samples/matter/common/src/bridge/bridged_device_data_provider.cpp b/samples/matter/common/src/bridge/bridged_device_data_provider.cpp new file mode 100644 index 00000000000..3cef34f51b9 --- /dev/null +++ b/samples/matter/common/src/bridge/bridged_device_data_provider.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include "bridged_device_data_provider.h" + +#include + +LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); + +CHIP_ERROR BridgedDeviceDataProvider::NotifyReachableStatusChange(bool isReachable) +{ + auto reachableContext = chip::Platform::New(); + if (!reachableContext) { + return CHIP_ERROR_NO_MEMORY; + } + + reachableContext->mIsReachable = isReachable; + reachableContext->mProvider = this; + + CHIP_ERROR err = chip::DeviceLayer::PlatformMgr().ScheduleWork( + [](intptr_t context) { + auto ctx = reinterpret_cast(context); + ctx->mProvider->NotifyUpdateState( + chip::app::Clusters::BridgedDeviceBasicInformation::Id, + chip::app::Clusters::BridgedDeviceBasicInformation::Attributes::Reachable::Id, + &ctx->mIsReachable, sizeof(ctx->mIsReachable)); + chip::Platform::Delete(ctx); + }, + reinterpret_cast(reachableContext)); + + if (CHIP_NO_ERROR != err) { + chip::Platform::Delete(reachableContext); + return err; + } + + return CHIP_NO_ERROR; +} diff --git a/samples/matter/common/src/bridge/bridged_device_data_provider.h b/samples/matter/common/src/bridge/bridged_device_data_provider.h index ed25375939a..238e7bf1354 100644 --- a/samples/matter/common/src/bridge/bridged_device_data_provider.h +++ b/samples/matter/common/src/bridge/bridged_device_data_provider.h @@ -21,6 +21,14 @@ class BridgedDeviceDataProvider { size_t dataSize) = 0; virtual CHIP_ERROR UpdateState(chip::ClusterId clusterId, chip::AttributeId attributeId, uint8_t *buffer) = 0; + CHIP_ERROR NotifyReachableStatusChange(bool isReachable); + protected: UpdateAttributeCallback mUpdateAttributeCallback; + +private: + struct ReachableContext { + bool mIsReachable; + BridgedDeviceDataProvider *mProvider; + }; };