8#include <esp_idf_version.h>
10#include <esp_heap_caps.h>
11#include <esp_system.h>
12#include <esp_chip_info.h>
13#include <esp_partition.h>
21static const char *
const TAG =
"debug";
25static const char *
const RESET_REASONS[] = {
29 "software via esp_restart",
34 "exiting deep sleep mode",
40 "power glitch detected",
44static const char *
const REBOOT_KEY =
"reboot_source";
45static const size_t REBOOT_MAX_LEN = 24;
50 char buffer[REBOOT_MAX_LEN]{};
54 strncpy(buffer, LOG_STR_ARG(
component->get_component_log_str()), REBOOT_MAX_LEN - 1);
55 buffer[REBOOT_MAX_LEN - 1] =
'\0';
57 ESP_LOGD(TAG,
"Storing reboot source: %s", buffer);
63 char *buf = buffer.data();
64 const size_t size = RESET_REASON_BUFFER_SIZE;
66 unsigned reason = esp_reset_reason();
67 if (reason <
sizeof(RESET_REASONS) /
sizeof(RESET_REASONS[0])) {
68 if (reason == ESP_RST_SW) {
71 char reboot_source[REBOOT_MAX_LEN]{};
72 if (pref.load(&reboot_source)) {
73 reboot_source[REBOOT_MAX_LEN - 1] =
'\0';
74 snprintf(buf,
size,
"Reboot request from %s", reboot_source);
76 snprintf(buf,
size,
"%s", RESET_REASONS[reason]);
79 snprintf(buf,
size,
"%s", RESET_REASONS[reason]);
82 snprintf(buf,
size,
"unknown source");
87#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
88static const char *
const WAKEUP_CAUSES[] = {
91 "external signal using RTC_IO",
92 "external signal using RTC_CNTL",
105 "VBAT under voltage",
108static const char *
const WAKEUP_CAUSES[] = {
111 "external signal using RTC_IO",
112 "external signal using RTC_CNTL",
126 static constexpr auto NUM_CAUSES =
sizeof(WAKEUP_CAUSES) /
sizeof(WAKEUP_CAUSES[0]);
127#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
129 uint32_t causes = esp_sleep_get_wakeup_causes();
131 return WAKEUP_CAUSES[0];
133 char *p = buffer.data();
134 char *
end = p + buffer.size();
136 const char *sep =
"";
137 for (
unsigned i = 0; i < NUM_CAUSES && p <
end; i++) {
138 if (causes & (1U << i)) {
139 size_t needed = strlen(sep) + strlen(WAKEUP_CAUSES[i]);
140 if (p + needed >=
end) {
143 p += snprintf(p,
end - p,
"%s%s", sep, WAKEUP_CAUSES[i]);
147 return buffer.data();
149 unsigned reason = esp_sleep_get_wakeup_cause();
150 if (reason < NUM_CAUSES) {
151 return WAKEUP_CAUSES[reason];
153 return "unknown source";
160 " %-12s %-4s %-8s %-10s %-10s",
161 "Name",
"Type",
"Subtype",
"Address",
"Size");
162 esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
164 const esp_partition_t *partition = esp_partition_get(it);
165 ESP_LOGCONFIG(TAG,
" %-12s %-4d %-8d 0x%08" PRIX32
" 0x%08" PRIX32, partition->label, partition->type,
166 partition->subtype, partition->address, partition->size);
167 it = esp_partition_next(it);
169 esp_partition_iterator_release(it);
179static constexpr ChipFeature CHIP_FEATURES[] = {
180 {CHIP_FEATURE_BLE,
"BLE"},
181 {CHIP_FEATURE_BT,
"BT"},
182 {CHIP_FEATURE_EMB_FLASH,
"EMB Flash"},
183 {CHIP_FEATURE_EMB_PSRAM,
"EMB PSRAM"},
184 {CHIP_FEATURE_WIFI_BGN,
"2.4GHz WiFi"},
188 constexpr size_t size = DEVICE_INFO_BUFFER_SIZE;
189 char *buf = buffer.data();
191#if defined(USE_ARDUINO)
192 const char *flash_mode;
193 switch (ESP.getFlashChipMode()) {
207 flash_mode =
"FAST_READ";
210 flash_mode =
"SLOW_READ";
213 flash_mode =
"UNKNOWN";
215 uint32_t flash_size = ESP.getFlashChipSize() / 1024;
216 uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000;
217 pos = buf_append_printf(buf,
size,
pos,
"|Flash: %" PRIu32
"kB Speed:%" PRIu32
"MHz Mode:%s", flash_size, flash_speed,
221 esp_chip_info_t info;
222 esp_chip_info(&info);
223 const char *model = ESPHOME_VARIANT;
229 bool first_feature =
true;
230 for (
const auto &feature : CHIP_FEATURES) {
231 if (info.features & feature.bit) {
234 first_feature =
false;
235 info.features &= ~feature.bit;
238 if (info.features != 0) {
240 pos = buf_append_printf(buf,
size,
pos,
"Other:0x%" PRIx32, info.features);
242 pos = buf_append_printf(buf,
size,
pos,
" Cores:%u Revision:%u", info.cores, info.revision);
245 pos = buf_append_printf(buf,
size,
pos,
"|CPU Frequency: %" PRIu32
" MHz", cpu_freq_mhz);
247 char reset_buffer[RESET_REASON_BUFFER_SIZE];
248 char wakeup_buffer[WAKEUP_CAUSE_BUFFER_SIZE];
249 const char *reset_reason =
get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reset_buffer));
250 const char *wakeup_cause =
get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE>(wakeup_buffer));
256 "ESP32 debug info:\n"
260 " CPU Frequency: %" PRIu32
" MHz\n"
261 " ESP-IDF Version: %s\n"
262 " EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X\n"
263 " Reset Reason: %s\n"
265 model, info.cores, info.revision, cpu_freq_mhz, esp_get_idf_version(), mac[0], mac[1], mac[2], mac[3],
266 mac[4], mac[5], reset_reason, wakeup_cause);
267#if defined(USE_ARDUINO)
268 ESP_LOGD(TAG,
" Flash: Size=%" PRIu32
"kB Speed=%" PRIu32
"MHz Mode=%s", flash_size, flash_speed, flash_mode);
272 ESP_LOGD(TAG,
" Framework: Arduino");
275 ESP_LOGD(TAG,
" Framework: ESP-IDF");
281 pos = buf_append_printf(buf,
size,
pos,
"|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3],
293 uint32_t max_alloc = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
301 uint32_t free_heap = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
303 float fragmentation = 100.0f - (100.0f * max_alloc / free_heap);
const StringRef & get_name() const
Get the name of this Application set by pre_setup().
Component * get_current_component()
constexpr const char * c_str() const
const char * get_wakeup_cause_(std::span< char, WAKEUP_CAUSE_BUFFER_SIZE > buffer)
sensor::Sensor * min_free_sensor_
void log_partition_info_()
Logs information about the device's partition table.
size_t get_device_info_(std::span< char, DEVICE_INFO_BUFFER_SIZE > buffer, size_t pos)
sensor::Sensor * fragmentation_sensor_
sensor::Sensor * psram_sensor_
void on_shutdown() override
uint32_t get_free_heap_()
sensor::Sensor * block_sensor_
const char * get_reset_reason_(std::span< char, RESET_REASON_BUFFER_SIZE > buffer)
void publish_state(float state)
Publish a new state to the front-end.
const Component * component
size_t buf_append_str(char *buf, size_t size, size_t pos, const char *str)
Safely append a string to buffer, returning new position (capped at size).
constexpr uint32_t fnv1_hash_extend(uint32_t hash, T value)
Extend a FNV-1 hash with an integer (hashes each byte).
ESPPreferences * global_preferences
uint32_t fnv1_hash(const char *str)
Calculate a FNV-1 hash of str.
uint32_t arch_get_cpu_freq_hz()
void get_mac_address_raw(uint8_t *mac)
Get the device MAC address as raw bytes, written into the provided byte array (6 bytes).
Application App
Global storage of Application pointer - only one Application can exist.
ESPPreferenceObject make_preference(size_t, uint32_t, bool)
bool sync()
Commit pending writes to flash.