Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ESP32] Diagnostic logs provider delegate implementation in temperature-meausement-app #31682

Merged
merged 7 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions config/esp32/components/chip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,12 @@ menu "CHIP Device Layer"

endmenu

config CHIP_ENABLE_BDX_LOG_TRANSFER
bool "Enable BDX log transfer"
default n
help
Enables the BDX protocol for diagnostics log transfer

menu "Matter OTA Image"

config CHIP_OTA_IMAGE_BUILD
Expand Down
30 changes: 30 additions & 0 deletions examples/temperature-measurement-app/esp32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ Usage:
./out/debug/chip-tool temperaturemeasurement read measured-value <NODE ID> 1
```

## Additional details

This example demonstrates the utilization of the diagnostic logs cluster to send
diagnostic logs to the client.

In this scenario, the [main/diagnostic_logs](main/diagnostic_logs) directory
contains three files:

```
main/diagnostic_logs
├── crash.log
├── end_user_support.log
└── network_diag.log
```

These files contain dummy data.

#### To test the diagnostic logs cluster

```
# Commission the app
chip-tool pairing ble-wifi 1 SSID PASSPHRASE 20202021 3840

# Read end user support logs using response payload protocol
chip-tool diagnosticlogs retrieve-logs-request 0 0 1 0

# Read network diagnostic using BDX protocol
chip-tool diagnosticlogs retrieve-logs-request 1 0 1 0 --TransferFileDesignator network-diag.log
```

## Optimization

Optimization related to WiFi, BLuetooth, Asserts etc are the part of this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ endif (CONFIG_ENABLE_PW_RPC)

idf_component_register(PRIV_INCLUDE_DIRS ${PRIV_INCLUDE_DIRS_LIST}
SRC_DIRS ${SRC_DIRS_LIST}
PRIV_REQUIRES ${PRIV_REQUIRES_LIST})
PRIV_REQUIRES ${PRIV_REQUIRES_LIST}
EMBED_FILES diagnostic_logs/end_user_support.log diagnostic_logs/network_diag.log diagnostic_logs/crash.log)

include("${CHIP_ROOT}/build/chip/esp32/esp32_codegen.cmake")
chip_app_component_codegen("${CHIP_ROOT}/examples/temperature-measurement-app/temperature-measurement-common/temperature-measurement.matter")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <diagnostic-logs-provider-delegate-impl.h>
#include <lib/support/SafeInt.h>

using namespace chip;
using namespace chip::app::Clusters::DiagnosticLogs;

LogProvider LogProvider::sInstance;

namespace {
bool IsValidIntent(IntentEnum intent)
{
return intent != IntentEnum::kUnknownEnumValue;
}

// end_user_support.log, network_diag.log, and crash.log files are embedded in the firmware
extern const uint8_t endUserSupportLogStart[] asm("_binary_end_user_support_log_start");
extern const uint8_t endUserSupportLogEnd[] asm("_binary_end_user_support_log_end");

extern const uint8_t networkDiagnosticLogStart[] asm("_binary_network_diag_log_start");
extern const uint8_t networkDiagnosticLogEnd[] asm("_binary_network_diag_log_end");

extern const uint8_t crashLogStart[] asm("_binary_crash_log_start");
extern const uint8_t crashLogEnd[] asm("_binary_crash_log_end");
} // namespace

LogProvider::~LogProvider()
{
for (auto sessionSpan : mSessionSpanMap)
{
Platform::MemoryFree(sessionSpan.second);
}
mSessionSpanMap.clear();
}

CHIP_ERROR LogProvider::GetLogForIntent(IntentEnum intent, MutableByteSpan & outBuffer, Optional<uint64_t> & outTimeStamp,
Optional<uint64_t> & outTimeSinceBoot)
{
CHIP_ERROR err = CHIP_NO_ERROR;
LogSessionHandle sessionHandle = kInvalidLogSessionHandle;

err = StartLogCollection(intent, sessionHandle, outTimeStamp, outTimeSinceBoot);
VerifyOrReturnError(CHIP_NO_ERROR == err, err, outBuffer.reduce_size(0));

bool unusedOutIsEndOfLog;
err = CollectLog(sessionHandle, outBuffer, unusedOutIsEndOfLog);
VerifyOrReturnError(CHIP_NO_ERROR == err, err, outBuffer.reduce_size(0));

err = EndLogCollection(sessionHandle);
VerifyOrReturnError(CHIP_NO_ERROR == err, err, outBuffer.reduce_size(0));

return CHIP_NO_ERROR;
}

const uint8_t * LogProvider::GetDataStartForIntent(IntentEnum intent)
{
switch (intent)
{
case IntentEnum::kEndUserSupport:
return &endUserSupportLogStart[0];
case IntentEnum::kNetworkDiag:
return &networkDiagnosticLogStart[0];
case IntentEnum::kCrashLogs:
return &crashLogStart[0];
default:
return nullptr;
}
}

size_t LogProvider::GetSizeForIntent(IntentEnum intent)
{
switch (intent)
{
case IntentEnum::kEndUserSupport:
return static_cast<size_t>(endUserSupportLogEnd - endUserSupportLogStart);
case IntentEnum::kNetworkDiag:
return static_cast<size_t>(networkDiagnosticLogEnd - networkDiagnosticLogStart);
case IntentEnum::kCrashLogs:
return static_cast<size_t>(crashLogEnd - crashLogStart);
default:
return 0;
}
}

CHIP_ERROR LogProvider::StartLogCollection(IntentEnum intent, LogSessionHandle & outHandle, Optional<uint64_t> & outTimeStamp,
Optional<uint64_t> & outTimeSinceBoot)
{
VerifyOrReturnValue(IsValidIntent(intent), CHIP_ERROR_INVALID_ARGUMENT);

const uint8_t * dataStart = GetDataStartForIntent(intent);
VerifyOrReturnError(dataStart, CHIP_ERROR_NOT_FOUND);

size_t dataSize = GetSizeForIntent(intent);
VerifyOrReturnError(dataSize, CHIP_ERROR_NOT_FOUND);

ByteSpan * span = reinterpret_cast<ByteSpan *>(Platform::MemoryCalloc(1, sizeof(ByteSpan)));
VerifyOrReturnValue(span, CHIP_ERROR_NO_MEMORY);

*span = ByteSpan(dataStart, dataSize);

mLogSessionHandle++;
// If the session handle rolls over to UINT16_MAX which is invalid, reset to 0.
VerifyOrDo(mLogSessionHandle != kInvalidLogSessionHandle, mLogSessionHandle = 0);

outHandle = mLogSessionHandle;
mSessionSpanMap[mLogSessionHandle] = span;
return CHIP_NO_ERROR;
}

CHIP_ERROR LogProvider::EndLogCollection(LogSessionHandle sessionHandle)
{
VerifyOrReturnValue(sessionHandle != kInvalidLogSessionHandle, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnValue(mSessionSpanMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);

ByteSpan * span = mSessionSpanMap[sessionHandle];
mSessionSpanMap.erase(sessionHandle);

Platform::MemoryFree(span);
return CHIP_NO_ERROR;
}

CHIP_ERROR LogProvider::CollectLog(LogSessionHandle sessionHandle, MutableByteSpan & outBuffer, bool & outIsEndOfLog)
{
VerifyOrReturnValue(sessionHandle != kInvalidLogSessionHandle, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnValue(mSessionSpanMap.count(sessionHandle), CHIP_ERROR_INVALID_ARGUMENT);

ByteSpan * span = mSessionSpanMap[sessionHandle];
auto dataSize = span->size();
auto count = std::min(dataSize, outBuffer.size());

VerifyOrReturnError(CanCastTo<off_t>(count), CHIP_ERROR_INVALID_ARGUMENT, outBuffer.reduce_size(0));

ReturnErrorOnFailure(CopySpanToMutableSpan(ByteSpan(span->data(), count), outBuffer));

outIsEndOfLog = dataSize == count;

if (!outIsEndOfLog)
{
// reduce the span after reading count bytes
*span = span->SubSpan(count);
}

return CHIP_NO_ERROR;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
W (5047Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.

Core 0 register dump:
PC : 0x4009579a PS : 0x00060c33 A0 : 0x800941e1 A1 : 0x3fff3630
0x4009579a: uxListRemove at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/list.c:195

A2 : 0x00000006 A3 : 0x00060c20 A4 : 0x00000000 A5 : 0x00060c23
A6 : 0xb33fffff A7 : 0xb33fffff A8 : 0x800950f0 A9 : 0x3fff3600
A10 : 0x00000001 A11 : 0x000000fe A12 : 0x00000000 A13 : 0x00000000
A14 : 0x00000000 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000016 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
0x4000c2e0: memcpy in ROM
0x4000c2f6: memcpy in ROM

Backtrace: 0x40095797:0x3fff3630 0x400941de:0x3fff3650 0x40154b39:0x3fff3670 0x40154b53:0x3fff3690 0x4013e20d:0x3fff36b0 0x40094fa6:0x3fff36d0
0x40095797: uxListRemove at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/list.c:202
0x400941de: vTaskDelete at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:1434 (discriminator 4)
0x40154b39: esp_nimble_disable at /opt/espressif/esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c:55
0x40154b53: nimble_port_freertos_deinit at /opt/espressif/esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c:80
0x4013e20d: chip::DeviceLayer::Internal::BLEManagerImpl::bleprph_host_task(void*) at /home/smart/projects/smp_matter/build/esp-idf/chip/../../../../../../../opt/espressif/esp-matter/connectedhomeip/connectedhomeip/config/esp32/third_party/connectedhomeip/src/platform/ESP32/nimble/BLEManagerImpl.cpp:864
0x40094fa6: vPortTaskWrapper at /opt/espressif/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
I (223374) chip[light]: Turning on the smart light.
I (233374) chip[light]: Setting smart light level to 78 %.
I (243374) chip[light]: Turning off the smart light.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
I (223374) chip[ndiag]: Wi-Fi connection status: 1
I (233374) chip[ndiag]: Wi-Fi RSSI: -67 dBm
I (243374) chip[ndiag]: Minimum ever Wi-Fi RSSI: -80 dBm
I (253374) chip[ndiag]: Wi-Fi disconnection count: 16
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <app/clusters/diagnostic-logs-server/DiagnosticLogsProviderDelegate.h>
#include <map>

namespace chip {
namespace app {
namespace Clusters {
namespace DiagnosticLogs {

/**
* The LogProvider class serves as the sole instance delegate for handling diagnostic logs.
*
* It implements the DiagnosticLogsProviderDelegate interface
*/

class LogProvider : public DiagnosticLogsProviderDelegate
{
public:
static inline LogProvider & GetInstance() { return sInstance; }

/////////// DiagnosticLogsProviderDelegate Interface /////////
CHIP_ERROR StartLogCollection(IntentEnum intent, LogSessionHandle & outHandle, Optional<uint64_t> & outTimeStamp,
Optional<uint64_t> & outTimeSinceBoot) override;
CHIP_ERROR EndLogCollection(LogSessionHandle sessionHandle) override;
CHIP_ERROR CollectLog(LogSessionHandle sessionHandle, MutableByteSpan & outBuffer, bool & outIsEndOfLog) override;
size_t GetSizeForIntent(IntentEnum intent) override;
CHIP_ERROR GetLogForIntent(IntentEnum intent, MutableByteSpan & outBuffer, Optional<uint64_t> & outTimeStamp,
Optional<uint64_t> & outTimeSinceBoot) override;

private:
static LogProvider sInstance;
LogProvider() = default;
~LogProvider();

LogProvider(const LogProvider &) = delete;
LogProvider & operator=(const LogProvider &) = delete;

// This tracks the ByteSpan for each session
std::map<LogSessionHandle, ByteSpan *> mSessionSpanMap;

LogSessionHandle mLogSessionHandle = kInvalidLogSessionHandle;

const uint8_t * GetDataStartForIntent(IntentEnum intent);
};

} // namespace DiagnosticLogs
} // namespace Clusters
} // namespace app
} // namespace chip
9 changes: 9 additions & 0 deletions examples/temperature-measurement-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "nvs_flash.h"
#include <app/clusters/diagnostic-logs-server/diagnostic-logs-server.h>
#include <app/server/Server.h>
#include <common/CHIPDeviceManager.h>
#include <common/Esp32AppServer.h>
#include <credentials/DeviceAttestationCredsProvider.h>
#include <credentials/examples/DeviceAttestationCredsExample.h>
#include <diagnostic-logs-provider-delegate-impl.h>
#include <platform/ESP32/ESP32Utils.h>

#include <cmath>
Expand Down Expand Up @@ -127,3 +129,10 @@ extern "C" void app_main()

chip::DeviceLayer::PlatformMgr().ScheduleWork(InitServer, reinterpret_cast<intptr_t>(nullptr));
}

using namespace chip::app::Clusters::DiagnosticLogs;
void emberAfDiagnosticLogsClusterInitCallback(chip::EndpointId endpoint)
{
auto & logProvider = LogProvider::GetInstance();
DiagnosticLogsServer::Instance().SetDiagnosticLogsProviderDelegate(endpoint, &logProvider);
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,6 @@ CONFIG_MBEDTLS_HKDF_C=y

# Increase LwIP IPv6 address number
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6

# Enable the diagnostic logs transfer over BDX protocol
CONFIG_CHIP_ENABLE_BDX_LOG_TRANSFER=y
Original file line number Diff line number Diff line change
Expand Up @@ -1452,10 +1452,15 @@ endpoint 0 {
}

server cluster DiagnosticLogs {
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
callback attribute attributeList;
ram attribute featureMap default = 0;
ram attribute clusterRevision default = 1;

handle command RetrieveLogsRequest;
handle command RetrieveLogsResponse;
}

server cluster GeneralDiagnostics {
Expand Down
Loading
Loading