1+ #include " HealthDiagnostics.h"
2+
3+ String HealthDiagnostics::getChipId () {
4+ #if defined(ESP32)
5+ return String ((uint32_t )ESP.getEfuseMac (), HEX);
6+ #elif defined(ESP8266)
7+ return String (ESP.getChipId (), HEX);
8+ #elif defined(ARDUINO_ARCH_RP2040)
9+ return String (rp2040.getChipID (), HEX);
10+ #endif
11+ }
12+
13+ void HealthDiagnostics::addHeapInfo (JsonObject& doc) {
14+ #if defined(ESP32)
15+ doc[" freeHeap" ] = ESP.getFreeHeap ();
16+ doc[" totalHeap" ] = ESP.getHeapSize ();
17+ doc[" minFreeHeap" ] = ESP.getMinFreeHeap ();
18+ doc[" maxAllocHeap" ] = ESP.getMaxAllocHeap ();
19+
20+ multi_heap_info_t heap_info;
21+ heap_caps_get_info (&heap_info, MALLOC_CAP_INTERNAL);
22+
23+ JsonObject internalHeap = doc[" internalHeap" ].to <JsonObject>();
24+ internalHeap[" totalFreeBytes" ] = heap_info.total_free_bytes ;
25+ internalHeap[" totalAllocatedBytes" ] = heap_info.total_allocated_bytes ;
26+ internalHeap[" largestFreeBlock" ] = heap_info.largest_free_block ;
27+ internalHeap[" minimumFreeBytes" ] = heap_info.minimum_free_bytes ;
28+ internalHeap[" allocatedBlocks" ] = heap_info.allocated_blocks ;
29+ internalHeap[" freeBlocks" ] = heap_info.free_blocks ;
30+ internalHeap[" totalBlocks" ] = heap_info.total_blocks ;
31+
32+ heap_caps_get_info (&heap_info, MALLOC_CAP_SPIRAM);
33+
34+ JsonObject psram = doc[" psram" ].to <JsonObject>();
35+ psram[" totalFreeBytes" ] = heap_info.total_free_bytes ;
36+ psram[" totalAllocatedBytes" ] = heap_info.total_allocated_bytes ;
37+ psram[" largestFreeBlock" ] = heap_info.largest_free_block ;
38+ psram[" minimumFreeBytes" ] = heap_info.minimum_free_bytes ;
39+ psram[" allocatedBlocks" ] = heap_info.allocated_blocks ;
40+ psram[" freeBlocks" ] = heap_info.free_blocks ;
41+ psram[" totalBlocks" ] = heap_info.total_blocks ;
42+
43+ #elif defined(ESP8266)
44+ doc[" freeHeap" ] = ESP.getFreeHeap ();
45+ doc[" heapFragmentation" ] = ESP.getHeapFragmentation ();
46+ doc[" maxFreeBlockSize" ] = ESP.getMaxFreeBlockSize ();
47+
48+ // Get detailed heap information.
49+ JsonObject heapInfo = doc[" heapInfo" ].to <JsonObject>();
50+ UMM_HEAP_INFO ummHeapInfo;
51+ umm_info (&ummHeapInfo, 0 );
52+ heapInfo[" freeBlocks" ] = ummHeapInfo.freeBlocks ;
53+ heapInfo[" usedBlocks" ] = ummHeapInfo.usedBlocks ;
54+ heapInfo[" totalBlocks" ] = ummHeapInfo.totalBlocks ;
55+ heapInfo[" totalEntries" ] = ummHeapInfo.totalEntries ;
56+ heapInfo[" usedEntries" ] = ummHeapInfo.usedEntries ;
57+ heapInfo[" freeEntries" ] = ummHeapInfo.freeEntries ;
58+ heapInfo[" maxFreeContiguousBytes" ] = umm_max_block_size ();
59+
60+ #elif defined(ARDUINO_ARCH_RP2040)
61+ doc[" freeHeap" ] = rp2040.getFreeHeap ();
62+ doc[" totalHeap" ] = rp2040.getTotalHeap ();
63+ #endif
64+ }
65+
66+ void HealthDiagnostics::addWiFiInfo (JsonObject& doc) {
67+ doc[" ssid" ] = WiFi.SSID ();
68+
69+ #if defined(ESP32) || defined(ESP8266)
70+ doc[" bssid" ] = WiFi.BSSIDstr ();
71+ #endif
72+
73+ doc[" rssi" ] = WiFi.RSSI ();
74+ doc[" ipAddress" ] = WiFi.localIP ().toString ();
75+ doc[" subnetMask" ] = WiFi.subnetMask ().toString ();
76+ doc[" gateway" ] = WiFi.gatewayIP ().toString ();
77+ doc[" dns" ] = WiFi.dnsIP ().toString ();
78+ doc[" macAddress" ] = WiFi.macAddress ();
79+ doc[" channel" ] = WiFi.channel ();
80+ }
81+
82+ void HealthDiagnostics::addSketchInfo (JsonObject& doc) {
83+ #if defined(ESP32) || defined(ESP8266)
84+ doc[" cpuFreq" ] = ESP.getCpuFreqMHz ();
85+ doc[" sketchSize" ] = ESP.getSketchSize ();
86+ doc[" freeSketchSpace" ] = ESP.getFreeSketchSpace ();
87+ doc[" flashChipSize" ] = ESP.getFlashChipSize ();
88+ doc[" flashChipSpeed" ] = ESP.getFlashChipSpeed ();
89+ #endif
90+ }
91+
92+ void HealthDiagnostics::addResetCause (JsonObject& doc) {
93+ #if defined(ESP32)
94+ switch (esp_reset_reason ()) {
95+ case ESP_RST_POWERON: doc[" reason" ] = " Power-on event" ; break ;
96+ case ESP_RST_EXT: doc[" reason" ] = " External pin reset" ; break ;
97+ case ESP_RST_SW: doc[" reason" ] = " Software reset via esp_restart" ; break ;
98+ case ESP_RST_PANIC: doc[" reason" ] = " Software reset due to exception/panic" ; break ;
99+ case ESP_RST_INT_WDT: doc[" reason" ] = " Reset (software or hardware) due to interrupt watchdog" ; break ;
100+ case ESP_RST_TASK_WDT: doc[" reason" ] = " Reset due to task watchdog" ; break ;
101+ case ESP_RST_WDT: doc[" reason" ] = " Reset due to other watchdogs" ; break ;
102+ case ESP_RST_DEEPSLEEP: doc[" reason" ] = " Deep sleep reset" ; break ;
103+ case ESP_RST_BROWNOUT: doc[" reason" ] = " Brownout reset" ; break ;
104+ case ESP_RST_SDIO: doc[" reason" ] = " Reset over SDIO" ; break ;
105+ default : doc[" reason" ] = " Unknown reset reason" ; break ;
106+ }
107+ #elif defined(ESP8266)
108+ doc[" reason" ] = ESP.getResetReason ();
109+ #endif
110+
111+ // doc["crashDetails"] = "" // Use something like https://github.com/krzychb/EspSaveCrash
112+ }
113+
114+ bool HealthDiagnostics::reportHealth (String& healthReport) {
115+ JsonDocument doc;
116+ doc[" chipId" ] = getChipId ();
117+ doc[" uptime" ] = millis () / 1000 ; // seconds
118+
119+ // Add detailed heap information.
120+ JsonObject heap = doc[" heap" ].to <JsonObject>();
121+ addHeapInfo (heap);
122+
123+ // Detailed Sketch information.
124+ JsonObject sketch = doc[" sketch" ].to <JsonObject>();
125+ addSketchInfo (sketch);
126+
127+ // Detailed WiFi information.
128+ JsonObject wifi = doc[" wifi" ].to <JsonObject>();
129+ addWiFiInfo (wifi);
130+
131+ // Add last reset reson
132+ JsonObject resetInfo = doc[" reset" ].to <JsonObject>();
133+ addResetCause (resetInfo);
134+
135+ serializeJson (doc, healthReport);
136+ return true ;
137+ }
0 commit comments