From c68f03d1fcf83b87a211f983802e2bdd90e3fa3a Mon Sep 17 00:00:00 2001 From: Kamil Kasperczyk Date: Fri, 12 Apr 2024 14:42:18 +0200 Subject: [PATCH] [clusters] Implemented ThreadDiagnosticDelegate Added ThreadDiagnosticDelegate to enable generation of optional events from ThreadNetworkDiagnostics cluster. Additionally implemented generation of ConnectionStatus and NetworkFaultChanged events when Thread link state is changed. --- .../thread-network-diagnostics-server.cpp | 59 +++++++++++++++++++ src/include/platform/DiagnosticDataProvider.h | 28 ++++++++- ...GenericThreadStackManagerImpl_OpenThread.h | 2 + ...nericThreadStackManagerImpl_OpenThread.hpp | 17 ++++++ 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp index b21f9015af8b28..0330377cf967ad 100644 --- a/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp +++ b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,9 @@ #include #include #include +#include +#include +#include using namespace chip; using namespace chip::app; @@ -132,6 +136,60 @@ CHIP_ERROR ThreadDiagosticsAttrAccess::Read(const ConcreteReadAttributePath & aP return CHIP_NO_ERROR; } +class ThreadDiagnosticsDelegate : public DeviceLayer::ThreadDiagnosticsDelegate +{ + // Notified when the Node’s connection status to a Thread network has changed. + void OnConnectionStatusChanged(ConnectionStatusEnum newConnectionStatus) override + { + ChipLogProgress(Zcl, "ThreadDiagnosticsDelegate: OnConnectionStatusChanged"); + + Events::ConnectionStatus::Type event{ newConnectionStatus }; + + // ThreadNetworkDiagnostics cluster should exist only for endpoint 0. + if (emberAfContainsServer(kRootEndpointId, ThreadNetworkDiagnostics::Id)) + { + // If Thread Network Diagnostics cluster is implemented on this endpoint + EventNumber eventNumber; + + if (CHIP_NO_ERROR != LogEvent(event, kRootEndpointId, eventNumber)) + { + ChipLogError(Zcl, "ThreadDiagnosticsDelegate: Failed to record ConnectionStatus event"); + } + } + } + + // Notified when the Node’s faults related to a Thread network have changed. + void OnNetworkFaultChanged(const GeneralFaults & previous, + const GeneralFaults & current) override + { + ChipLogProgress(Zcl, "ThreadDiagnosticsDelegate: OnNetworkFaultChanged"); + + /* Verify that the data size matches the expected one. */ + static_assert(sizeof(*current.data()) == sizeof(NetworkFaultEnum)); + + DataModel::List currentList(reinterpret_cast(current.data()), + current.size()); + DataModel::List previousList(reinterpret_cast(previous.data()), + previous.size()); + + Events::NetworkFaultChange::Type event{ currentList, previousList }; + + // ThreadNetworkDiagnostics cluster should exist only for endpoint 0. + if (emberAfContainsServer(kRootEndpointId, ThreadNetworkDiagnostics::Id)) + { + // If Thread Network Diagnostics cluster is implemented on this endpoint + EventNumber eventNumber; + + if (CHIP_NO_ERROR != LogEvent(event, kRootEndpointId, eventNumber)) + { + ChipLogError(Zcl, "ThreadDiagnosticsDelegate: Failed to record NetworkFaultChange event"); + } + } + } +}; + +ThreadDiagnosticsDelegate gDiagnosticDelegate; + } // anonymous namespace bool emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(app::CommandHandler * commandObj, @@ -146,4 +204,5 @@ bool emberAfThreadNetworkDiagnosticsClusterResetCountsCallback(app::CommandHandl void MatterThreadNetworkDiagnosticsPluginServerInitCallback() { registerAttributeAccessOverride(&gAttrAccess); + GetDiagnosticDataProvider().SetThreadDiagnosticsDelegate(&gDiagnosticDelegate); } diff --git a/src/include/platform/DiagnosticDataProvider.h b/src/include/platform/DiagnosticDataProvider.h index a99ca6ee61beb1..2430673bc55724 100644 --- a/src/include/platform/DiagnosticDataProvider.h +++ b/src/include/platform/DiagnosticDataProvider.h @@ -91,6 +91,29 @@ class WiFiDiagnosticsDelegate virtual void OnConnectionStatusChanged(uint8_t connectionStatus) {} }; +/** + * Defines the Thread Diagnostics Delegate class to notify Thread network events. + */ +class ThreadDiagnosticsDelegate +{ +public: + virtual ~ThreadDiagnosticsDelegate() {} + + /** + * @brief + * Called when the Node’s connection status to a Thread network has changed. + */ + virtual void OnConnectionStatusChanged(app::Clusters::ThreadNetworkDiagnostics::ConnectionStatusEnum newConnectionStatus) {} + + /** + * @brief + * Called when the Node detects change in the set of current Thread network faults. + */ + virtual void OnNetworkFaultChanged(const GeneralFaults & previous, + const GeneralFaults & current) + {} +}; + /** * Provides access to runtime and build-time configuration information for a chip device. */ @@ -99,6 +122,8 @@ class DiagnosticDataProvider public: void SetWiFiDiagnosticsDelegate(WiFiDiagnosticsDelegate * delegate) { mWiFiDiagnosticsDelegate = delegate; } WiFiDiagnosticsDelegate * GetWiFiDiagnosticsDelegate() const { return mWiFiDiagnosticsDelegate; } + void SetThreadDiagnosticsDelegate(ThreadDiagnosticsDelegate * delegate) { mThreadDiagnosticsDelegate = delegate; } + ThreadDiagnosticsDelegate * GetThreadDiagnosticsDelegate() const { return mThreadDiagnosticsDelegate; } /** * General Diagnostics methods. @@ -238,7 +263,8 @@ class DiagnosticDataProvider virtual ~DiagnosticDataProvider() = default; private: - WiFiDiagnosticsDelegate * mWiFiDiagnosticsDelegate = nullptr; + WiFiDiagnosticsDelegate * mWiFiDiagnosticsDelegate = nullptr; + ThreadDiagnosticsDelegate * mThreadDiagnosticsDelegate = nullptr; // No copy, move or assignment. DiagnosticDataProvider(const DiagnosticDataProvider &) = delete; diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h index 896c5ef0f54f22..6b9e1f7432612c 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h @@ -40,6 +40,7 @@ #include #include #include +#include #include namespace chip { @@ -229,6 +230,7 @@ class GenericThreadStackManagerImpl_OpenThread DnsBrowseCallback mDnsBrowseCallback; DnsResolveCallback mDnsResolveCallback; + GeneralFaults mNetworkFaults; struct DnsServiceTxtEntries { diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp index 15f9f80115cd3a..7c3111a2082339 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -223,6 +224,22 @@ void GenericThreadStackManagerImpl_OpenThread::_OnPlatformEvent(const { ChipLogError(DeviceLayer, "Failed to post Thread connectivity change: %" CHIP_ERROR_FORMAT, status.Format()); } + + ThreadDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetThreadDiagnosticsDelegate(); + + if (mIsAttached) + { + delegate->OnConnectionStatusChanged(app::Clusters::ThreadNetworkDiagnostics::ConnectionStatusEnum::kConnected); + } + else + { + delegate->OnConnectionStatusChanged(app::Clusters::ThreadNetworkDiagnostics::ConnectionStatusEnum::kNotConnected); + + GeneralFaults current; + current.add(to_underlying(chip::app::Clusters::ThreadNetworkDiagnostics::NetworkFaultEnum::kLinkDown)); + delegate->OnNetworkFaultChanged(mNetworkFaults, current); + mNetworkFaults = current; + } } #if CHIP_DETAIL_LOGGING