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 59115c0971..c2e198736f 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 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +31,9 @@ #include #include #include +#include +#include +#include using namespace chip; using namespace chip::app; @@ -133,6 +137,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, @@ -147,4 +205,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 a99ca6ee61..2430673bc5 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 896c5ef0f5..6b9e1f7432 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 15f9f80115..7c3111a208 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