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