9#include <esp_idf_version.h>
11#include <esp_heap_caps.h>
12#include <esp_system.h>
13#include <esp_chip_info.h>
14#include <esp_partition.h>
22static const char *
const TAG =
"debug";
26static const char *
const RESET_REASONS[] = {
30 "software via esp_restart",
35 "exiting deep sleep mode",
41 "power glitch detected",
45static const char *
const REBOOT_KEY =
"reboot_source";
46static const size_t REBOOT_MAX_LEN = 24;
51 char buffer[REBOOT_MAX_LEN]{};
55 strncpy(buffer, LOG_STR_ARG(
component->get_component_log_str()), REBOOT_MAX_LEN - 1);
56 buffer[REBOOT_MAX_LEN - 1] =
'\0';
58 ESP_LOGD(TAG,
"Storing reboot source: %s", buffer);
64 char *buf = buffer.data();
65 const size_t size = RESET_REASON_BUFFER_SIZE;
67 unsigned reason = esp_reset_reason();
68 if (reason <
sizeof(RESET_REASONS) /
sizeof(RESET_REASONS[0])) {
69 if (reason == ESP_RST_SW) {
72 char reboot_source[REBOOT_MAX_LEN]{};
73 if (pref.load(&reboot_source)) {
74 reboot_source[REBOOT_MAX_LEN - 1] =
'\0';
75 snprintf(buf,
size,
"Reboot request from %s", reboot_source);
77 snprintf(buf,
size,
"%s", RESET_REASONS[reason]);
80 snprintf(buf,
size,
"%s", RESET_REASONS[reason]);
83 snprintf(buf,
size,
"unknown source");
88#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
89static const char *
const WAKEUP_CAUSES[] = {
92 "external signal using RTC_IO",
93 "external signal using RTC_CNTL",
106 "VBAT under voltage",
109static const char *
const WAKEUP_CAUSES[] = {
112 "external signal using RTC_IO",
113 "external signal using RTC_CNTL",
127 static constexpr auto NUM_CAUSES =
sizeof(WAKEUP_CAUSES) /
sizeof(WAKEUP_CAUSES[0]);
128#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(6, 0, 0)
130 uint32_t causes = esp_sleep_get_wakeup_causes();
132 return WAKEUP_CAUSES[0];
134 char *p = buffer.data();
135 char *
end = p + buffer.size();
137 const char *sep =
"";
138 for (
unsigned i = 0; i < NUM_CAUSES && p <
end; i++) {
139 if (causes & (1U << i)) {
140 size_t needed = strlen(sep) + strlen(WAKEUP_CAUSES[i]);
141 if (p + needed >=
end) {
144 p += snprintf(p,
end - p,
"%s%s", sep, WAKEUP_CAUSES[i]);
148 return buffer.data();
150 unsigned reason = esp_sleep_get_wakeup_cause();
151 if (reason < NUM_CAUSES) {
152 return WAKEUP_CAUSES[reason];
154 return "unknown source";
161 " %-12s %-4s %-8s %-10s %-10s",
162 "Name",
"Type",
"Subtype",
"Address",
"Size");
163 esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
165 const esp_partition_t *partition = esp_partition_get(it);
166 ESP_LOGCONFIG(TAG,
" %-12s %-4d %-8d 0x%08" PRIX32
" 0x%08" PRIX32, partition->label, partition->type,
167 partition->subtype, partition->address, partition->size);
168 it = esp_partition_next(it);
170 esp_partition_iterator_release(it);
180static constexpr ChipFeature CHIP_FEATURES[] = {
181 {CHIP_FEATURE_BLE,
"BLE"},
182 {CHIP_FEATURE_BT,
"BT"},
183 {CHIP_FEATURE_EMB_FLASH,
"EMB Flash"},
184 {CHIP_FEATURE_EMB_PSRAM,
"EMB PSRAM"},
185 {CHIP_FEATURE_WIFI_BGN,
"2.4GHz WiFi"},
189 constexpr size_t size = DEVICE_INFO_BUFFER_SIZE;
190 char *buf = buffer.data();
192#if defined(USE_ARDUINO)
193 const char *flash_mode;
194 switch (ESP.getFlashChipMode()) {
208 flash_mode =
"FAST_READ";
211 flash_mode =
"SLOW_READ";
214 flash_mode =
"UNKNOWN";
216 uint32_t flash_size = ESP.getFlashChipSize() / 1024;
217 uint32_t flash_speed = ESP.getFlashChipSpeed() / 1000000;
218 pos = buf_append_printf(buf,
size,
pos,
"|Flash: %" PRIu32
"kB Speed:%" PRIu32
"MHz Mode:%s", flash_size, flash_speed,
222 esp_chip_info_t info;
223 esp_chip_info(&info);
224 const char *model = ESPHOME_VARIANT;
230 bool first_feature =
true;
231 for (
const auto &feature : CHIP_FEATURES) {
232 if (info.features & feature.bit) {
235 first_feature =
false;
236 info.features &= ~feature.bit;
239 if (info.features != 0) {
241 pos = buf_append_printf(buf,
size,
pos,
"Other:0x%" PRIx32, info.features);
243 pos = buf_append_printf(buf,
size,
pos,
" Cores:%u Revision:%u", info.cores, info.revision);
246 pos = buf_append_printf(buf,
size,
pos,
"|CPU Frequency: %" PRIu32
" MHz", cpu_freq_mhz);
248 char reset_buffer[RESET_REASON_BUFFER_SIZE];
249 char wakeup_buffer[WAKEUP_CAUSE_BUFFER_SIZE];
250 const char *reset_reason =
get_reset_reason_(std::span<char, RESET_REASON_BUFFER_SIZE>(reset_buffer));
251 const char *wakeup_cause =
get_wakeup_cause_(std::span<char, WAKEUP_CAUSE_BUFFER_SIZE>(wakeup_buffer));
253 uint8_t mac[MAC_ADDRESS_SIZE];
257 "ESP32 debug info:\n"
261 " CPU Frequency: %" PRIu32
" MHz\n"
262 " ESP-IDF Version: %s\n"
263 " EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X\n"
264 " Reset Reason: %s\n"
266 model, info.cores, info.revision, cpu_freq_mhz, esp_get_idf_version(), mac[0], mac[1], mac[2], mac[3],
267 mac[4], mac[5], reset_reason, wakeup_cause);
268#if defined(USE_ARDUINO)
269 ESP_LOGD(TAG,
" Flash: Size=%" PRIu32
"kB Speed=%" PRIu32
"MHz Mode=%s", flash_size, flash_speed, flash_mode);
273 ESP_LOGD(TAG,
" Framework: Arduino");
276 ESP_LOGD(TAG,
" Framework: ESP-IDF");
282 pos = buf_append_printf(buf,
size,
pos,
"|EFuse MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3],
294 uint32_t max_alloc = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL);
302 uint32_t free_heap = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
304 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.