[clusters] Implemented ThreadDiagnosticDelegate (#32964)
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.
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 59115c0..c2e1987 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 <app/AttributeAccessInterfaceRegistry.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
+#include <app/EventLogging.h>
#include <app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.h>
#include <app/util/attribute-storage.h>
#include <lib/core/CHIPEncoding.h>
@@ -30,6 +31,9 @@
#include <lib/core/TLVTypes.h>
#include <lib/support/CHIPPlatformMemory.h>
#include <platform/CHIPDeviceLayer.h>
+#include <platform/DiagnosticDataProvider.h>
+#include <tracing/macros.h>
+#include <tracing/metric_event.h>
using namespace chip;
using namespace chip::app;
@@ -133,6 +137,60 @@
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<kMaxNetworkFaults> & previous,
+ const GeneralFaults<kMaxNetworkFaults> & current) override
+ {
+ ChipLogProgress(Zcl, "ThreadDiagnosticsDelegate: OnNetworkFaultChanged");
+
+ /* Verify that the data size matches the expected one. */
+ static_assert(sizeof(*current.data()) == sizeof(NetworkFaultEnum));
+
+ DataModel::List<const NetworkFaultEnum> currentList(reinterpret_cast<const NetworkFaultEnum *>(current.data()),
+ current.size());
+ DataModel::List<const NetworkFaultEnum> previousList(reinterpret_cast<const NetworkFaultEnum *>(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 @@
void MatterThreadNetworkDiagnosticsPluginServerInitCallback()
{
registerAttributeAccessOverride(&gAttrAccess);
+ GetDiagnosticDataProvider().SetThreadDiagnosticsDelegate(&gDiagnosticDelegate);
}
diff --git a/src/include/platform/DiagnosticDataProvider.h b/src/include/platform/DiagnosticDataProvider.h
index a99ca6e..2430673 100644
--- a/src/include/platform/DiagnosticDataProvider.h
+++ b/src/include/platform/DiagnosticDataProvider.h
@@ -92,6 +92,29 @@
};
/**
+ * 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<kMaxNetworkFaults> & previous,
+ const GeneralFaults<kMaxNetworkFaults> & current)
+ {}
+};
+
+/**
* Provides access to runtime and build-time configuration information for a chip device.
*/
class DiagnosticDataProvider
@@ -99,6 +122,8 @@
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 @@
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 896c5ef..6b9e1f7 100644
--- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h
+++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h
@@ -40,6 +40,7 @@
#include <app/icd/server/ICDServerConfig.h>
#include <lib/dnssd/Advertiser.h>
#include <lib/dnssd/platform/Dnssd.h>
+#include <platform/GeneralFaults.h>
#include <platform/NetworkCommissioning.h>
namespace chip {
@@ -229,6 +230,7 @@
DnsBrowseCallback mDnsBrowseCallback;
DnsResolveCallback mDnsResolveCallback;
+ GeneralFaults<kMaxNetworkFaults> mNetworkFaults;
struct DnsServiceTxtEntries
{
diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp
index 15f9f80..7c3111a 100644
--- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp
+++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp
@@ -52,6 +52,7 @@
#include <lib/support/FixedBufferAllocator.h>
#include <lib/support/ThreadOperationalDataset.h>
#include <lib/support/logging/CHIPLogging.h>
+#include <platform/DiagnosticDataProvider.h>
#include <platform/OpenThread/GenericNetworkCommissioningThreadDriver.h>
#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
#include <platform/OpenThread/OpenThreadUtils.h>
@@ -223,6 +224,22 @@
{
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<kMaxNetworkFaults> current;
+ current.add(to_underlying(chip::app::Clusters::ThreadNetworkDiagnostics::NetworkFaultEnum::kLinkDown));
+ delegate->OnNetworkFaultChanged(mNetworkFaults, current);
+ mNetworkFaults = current;
+ }
}
#if CHIP_DETAIL_LOGGING