debug: rework boot info and terminal commands

- reduce info lines on boot
- more compact `info` command. show versions, modules and crash info when there is one
- add `storage` command to display flash layout (experimental)
- display full chip id aka MAC, including the oui
- fix telnet never printing the crash data b/c telnet in not yet authorized
- fix eeprom size not reflecting the space used by the backup sectors
- use static flash strings when possible for the fw info
This commit is contained in:
Maxim Prokhorov
2021-04-07 03:24:21 +03:00
parent 0ee55ba5c0
commit 7ea735548b
18 changed files with 657 additions and 960 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -9,14 +9,11 @@ BOARD MODULE
#include <Arduino.h>
const String& getChipId();
const String& getFullChipId();
const String& getIdentifier();
String getEspurnaModules();
String getEspurnaOTAModules();
String getEspurnaSensors();
const char* getEspurnaModules();
const char* getEspurnaSensors();
const char* getEspurnaWebUI();
String getEspurnaWebUI();
bool isEspurnaCore();
int getBoardId();
void boardSetup();

View File

@@ -8,6 +8,16 @@ COMPATIBILITY BETWEEN 2.3.0 and latest versions
#include "espurna.h"
// -----------------------------------------------------------------------------
inline constexpr bool isEspurnaCore() {
#if defined(ESPURNA_CORE) || defined(ESPURNA_CORE_WEBUI)
return true;
#else
return false;
#endif
}
// -----------------------------------------------------------------------------
// Core version 2.4.2 and higher changed the cont_t structure to a pointer:
// https://github.com/esp8266/Arduino/commit/5d5ea92a4d004ab009d5f642629946a0cb8893dd#diff-3fa12668b289ccb95b7ab334833a4ba8L35

View File

@@ -21,8 +21,11 @@ Copyright (C) 2019-2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com
#include <stdarg.h>
#include "system.h"
#include "rtcmem.h"
#include "storage_eeprom.h"
constexpr uint32_t EmptyTimestamp { 0xffffffff };
bool _save_crash_enabled = true;
size_t crashReservedSize() {
@@ -101,8 +104,7 @@ extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack
* Clears crash info CRASH_TIME value, later checked in crashDump()
*/
void crashClear() {
uint32_t crash_time = 0xFFFFFFFF;
eepromPut(EepromCrashBegin + SAVE_CRASH_CRASH_TIME, crash_time);
eepromPut(EepromCrashBegin + SAVE_CRASH_CRASH_TIME, EmptyTimestamp);
eepromCommit();
}
@@ -119,14 +121,14 @@ void _crashDump(Print& print, bool check) {
uint32_t crash_time;
eepromGet(EepromCrashBegin + SAVE_CRASH_CRASH_TIME, crash_time);
bool crash_time_erased = ((crash_time == 0) || (crash_time == 0xFFFFFFFF));
bool crash_time_erased = ((crash_time == 0) || (crash_time == EmptyTimestamp));
if (check && crash_time_erased) {
return;
}
uint8_t reason = eepromRead(EepromCrashBegin + SAVE_CRASH_RESTART_REASON);
if (!crash_time_erased) {
snprintf_P(buffer, sizeof(buffer), PSTR("\nLatest crash was at %lu ms after boot\n"), crash_time);
snprintf_P(buffer, sizeof(buffer), PSTR("\nlatest crash was at %lu ms after boot\n"), crash_time);
print.print(buffer);
}
@@ -214,12 +216,7 @@ void _crashDump(Print& print, bool check) {
#if TERMINAL_SUPPORT
void _crashTerminalCommand(const terminal::CommandContext& ctx) {
if ((ctx.argc == 2) && (ctx.argv[1].equals(F("force")))) {
crashForceDump(ctx.output);
} else {
crashDump(ctx.output);
crashClear();
}
crashForceDump(ctx.output);
terminalOK(ctx);
}
@@ -235,14 +232,30 @@ void crashDump(Print& print) {
_crashDump(print, true);
}
void crashSetup() {
void crashResetReason(Print& print) {
auto reason = customResetReason();
bool custom { CustomResetReason::None != reason };
print.printf_P(PSTR("last reset reason: %s\n"), custom
? customResetReasonToPayload(reason).c_str()
: ESP.getResetReason().c_str());
#if TERMINAL_SUPPORT
terminalRegisterCommand(F("CRASH"), _crashTerminalCommand);
#endif
if (!custom) {
print.printf_P(PSTR("extra info: %s\n"), ESP.getResetInfo().c_str());
}
crashDump(print);
}
void crashSetup() {
if (!rtcmemStatus()) {
crashClear();
}
#if TERMINAL_SUPPORT
terminalRegisterCommand(F("CRASH"), _crashTerminalCommand);
#endif
_save_crash_enabled = getSetting("sysCrashSave", 1 == SAVE_CRASH_ENABLED);
}
#endif // DEBUG_SUPPORT

View File

@@ -58,6 +58,7 @@ constexpr size_t CrashTraceReservedSize = CrashReservedSize - SAVE_CRASH_STACK_T
size_t crashReservedSize();
void crashResetReason(Print&);
void crashForceDump(Print&);
void crashDump(Print&);
void crashClear();

View File

@@ -35,7 +35,6 @@ char _udp_syslog_header[64];
bool _debug_enabled = false;
// -----------------------------------------------------------------------------
// printf-like debug methods
// -----------------------------------------------------------------------------
@@ -376,8 +375,11 @@ bool _debugHeartbeat(heartbeat::Mask mask) {
if (mask & heartbeat::Report::Uptime)
DEBUG_MSG_P(PSTR("[MAIN] Uptime: %s\n"), getUptime().c_str());
if (mask & heartbeat::Report::Freeheap)
infoHeapStats();
if (mask & heartbeat::Report::Freeheap) {
auto stats = systemHeapStats();
DEBUG_MSG_P(PSTR("[MAIN] %5u / %5u bytes available (%5u contiguous)\n"),
stats.available, systemInitialFreeHeap(), stats.usable);
}
if ((mask & heartbeat::Report::Vcc) && (ADC_MODE_VALUE == ADC_VCC))
DEBUG_MSG_P(PSTR("[MAIN] Power: %lu mV\n"), ESP.getVcc());

View File

@@ -65,7 +65,7 @@ public:
Strings(const Strings&) = delete;
Strings(Strings&&) = default;
Strings(String&& prefix_, String&& name_, const String& identifier_, const String& version_, const String& manufacturer_, const String& device_) :
Strings(String&& prefix_, String&& name_, const String& identifier_, const char* version_, const char* manufacturer_, const char* device_) :
prefix(std::move(prefix_)),
name(std::move(name_)),
identifier(identifier_),
@@ -80,9 +80,9 @@ public:
String prefix;
String name;
String identifier;
String version;
String manufacturer;
String device;
const char* version;
const char* manufacturer;
const char* device;
};
using StringsPtr = std::unique_ptr<Strings>;
@@ -96,7 +96,7 @@ public:
Device(const Device&) = delete;
Device(Device&&) = default;
Device(String&& prefix, String&& name, const String& identifier, const String& version, const String& manufacturer, const String& device) :
Device(String&& prefix, String&& name, const String& identifier, const char* version, const char* manufacturer, const char* device) :
_strings(std::make_unique<Strings>(std::move(prefix), std::move(name), identifier, version, manufacturer, device)),
_buffer(std::make_unique<Buffer>()),
_root(_buffer->createObject())
@@ -105,9 +105,9 @@ public:
ids.add(_strings->identifier.c_str());
_root["name"] = _strings->name.c_str();
_root["sw"] = _strings->version.c_str();
_root["mf"] = _strings->manufacturer.c_str();
_root["mdl"] = _strings->device.c_str();
_root["sw"] = _strings->version;
_root["mf"] = _strings->manufacturer;
_root["mdl"] = _strings->device;
}
const String& name() const {

View File

@@ -116,9 +116,7 @@ void setup() {
}
setBoardName();
// Show welcome message and system configuration
info(true);
boardSetup();
wifiSetup();
otaSetup();
@@ -290,6 +288,7 @@ void setup() {
if (_loop_delay != loop_delay) {
setSetting("loopDelay", _loop_delay);
}
}
void loop() {

View File

@@ -620,7 +620,7 @@ bool _mqttHeartbeat(heartbeat::Mask mask) {
mqttSend(MQTT_TOPIC_APP, APP_NAME);
if (mask & heartbeat::Report::Version)
mqttSend(MQTT_TOPIC_VERSION, getVersion().c_str());
mqttSend(MQTT_TOPIC_VERSION, getVersion());
if (mask & heartbeat::Report::Board)
mqttSend(MQTT_TOPIC_BOARD, getBoardName().c_str());

View File

@@ -48,7 +48,7 @@ void eepromSetup();
extern EEPROM_Rotate EEPROMr;
inline unsigned long eepromSpace() {
return EEPROMr.reserved() * SPI_FLASH_SEC_SIZE;
return EEPROMr.size() * SPI_FLASH_SEC_SIZE;
}
inline void eepromClear() {

View File

@@ -23,6 +23,8 @@ Updated to use WiFiServer and support reverse connections by Niek van der Maas <
#include <vector>
#include "board.h"
#include "crash.h"
#include "terminal.h"
#include "ws.h"
#if TELNET_SERVER == TELNET_SERVER_ASYNC
@@ -360,14 +362,6 @@ void _telnetNotifyConnected(unsigned char i) {
DEBUG_MSG_P(PSTR("[TELNET] Client #%u connected\n"), i);
// If there is no terminal support automatically dump info and crash data
#if DEBUG_SUPPORT
#if not TERMINAL_SUPPORT
crashDump(terminalDefaultStream());
crashClear();
#endif
#endif
if (!isEspurnaCore()) {
_telnetClientsAuth[i] = !_telnetAuth;
if (_telnetAuth) {
@@ -381,6 +375,10 @@ void _telnetNotifyConnected(unsigned char i) {
_telnetClientsAuth[i] = true;
}
#if DEBUG_SUPPORT
crashResetReason(terminalDefaultStream());
#endif
}
#if TELNET_SERVER == TELNET_SERVER_WIFISERVER

View File

@@ -12,6 +12,7 @@ Copyright (C) 2020 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#if TERMINAL_SUPPORT
#include "api.h"
#include "crash.h"
#include "settings.h"
#include "system.h"
#include "telnet.h"
@@ -269,6 +270,107 @@ void start(String&& hostname, Callback&& callback) {
} // namespace dns
extern "C" uint32_t _FS_start;
extern "C" uint32_t _FS_end;
struct Layout {
Layout() = delete;
constexpr Layout(const Layout&) = default;
constexpr Layout(Layout&&) = default;
constexpr Layout(const char* const name, uint32_t start, uint32_t end) :
_name(name),
_start(start),
_end(end)
{}
constexpr uint32_t size() const {
return _end - _start;
}
constexpr uint32_t start() const {
return _start;
}
constexpr uint32_t end() const {
return _end;
}
constexpr const char* name() const {
return _name;
}
private:
const char* const _name;
uint32_t _start;
uint32_t _end;
};
struct Layouts {
using List = std::forward_list<Layout>;
Layouts() = delete;
explicit Layouts(uint32_t size) :
_size(size),
_current(size),
_sectors(size / SPI_FLASH_SEC_SIZE)
{}
const Layout* head() const {
if (_list.empty()) {
return nullptr;
}
return &_list.front();
}
bool lock() {
if (_lock) {
return true;
}
_lock = true;
return false;
}
uint32_t sectors() const {
return _sectors;
}
uint32_t size() const {
return _size - _current;
}
uint32_t current() const {
return _current;
}
Layouts& add(const char* const name, uint32_t size) {
if (!_lock && _current >= size) {
Layout layout(name, _current - size, _current);
_current -= layout.size();
_list.push_front(layout);
}
return *this;
}
template <typename T>
void foreach(T&& callback) {
for (auto& layout : _list) {
callback(layout);
}
}
private:
bool _lock { false };
List _list;
uint32_t _size;
uint32_t _current;
uint32_t _sectors;
};
void _terminalInitCommands() {
terminalRegisterCommand(F("COMMANDS"), _terminalHelpCommand);
@@ -345,9 +447,62 @@ void _terminalInitCommands() {
terminalOK(ctx);
});
terminalRegisterCommand(F("INFO"), [](const terminal::CommandContext&) {
info();
terminalOK();
terminalRegisterCommand(F("INFO"), [](const terminal::CommandContext& ctx) {
if (!systemCheck()) {
ctx.output.print(F("\n\n!!! device is in safe mode !!!\n\n"));
}
ctx.output.printf_P(PSTR(APP_NAME " %s built %s\n"), getVersion(), buildTime().c_str());
ctx.output.printf_P(PSTR("mcu: esp8266 chipid: %s\n"), getFullChipId().c_str());
ctx.output.printf_P(PSTR("sdk: %s core: %s\n"),
ESP.getSdkVersion(), getCoreVersion().c_str());
ctx.output.printf_P(PSTR("md5: %s\n"), ESP.getSketchMD5().c_str());
ctx.output.printf_P(PSTR("support: %s\n"), getEspurnaModules());
#if SENSOR_SUPPORT
ctx.output.printf_P(PSTR("sensors: %s\n"), getEspurnaSensors());
#endif
#if DEBUG_SUPPORT
crashResetReason(ctx.output);
#endif
terminalOK(ctx);
});
terminalRegisterCommand(F("STORAGE"), [](const terminal::CommandContext& ctx) {
ctx.output.printf_P(PSTR("flash chip ID: 0x%06X\n"), ESP.getFlashChipId());
ctx.output.printf_P(PSTR("speed: %u\n"), ESP.getFlashChipSpeed());
ctx.output.printf_P(PSTR("mode: %s\n"), getFlashChipMode());
ctx.output.printf_P(PSTR("size: %u (SPI), %u (SDK)\n"),
ESP.getFlashChipRealSize(), ESP.getFlashChipSize());
Layouts layout(ESP.getFlashChipRealSize());
// SDK specifies a hard-coded layout, there's no data beyond
// (...addressable by the Core, since it adheres the setting)
if (ESP.getFlashChipRealSize() > ESP.getFlashChipSize()) {
layout.add("unused", ESP.getFlashChipRealSize() - ESP.getFlashChipSize());
}
// app is at a normal location, [0...size), but... since it is offset by the free space, make sure it is aligned
// to the sector size (...and it is expected from the getFreeSketchSpace, as the app will align to use the fixed
// sector address for OTA writes).
layout.add("sdk", 4 * SPI_FLASH_SEC_SIZE);
layout.add("eeprom", eepromSpace());
auto app_size = (ESP.getSketchSize() + FLASH_SECTOR_SIZE - 1) & (~(FLASH_SECTOR_SIZE - 1));
auto ota_size = layout.current() - app_size;
// OTA is allowed to use all but one eeprom sectors that, leaving the last one
// for the settings snapshot during the update
layout.add("ota", ota_size);
layout.add("app", app_size);
layout.foreach([&](const Layout& l) {
ctx.output.printf_P("%-6s [%08X...%08X) (%u bytes)\n", l.name(), l.start(), l.end(), l.size());
});
});
terminalRegisterCommand(F("RESET"), [](const terminal::CommandContext& ctx) {
@@ -371,7 +526,7 @@ void _terminalInitCommands() {
#if SECURE_CLIENT == SECURE_CLIENT_BEARSSL
terminalRegisterCommand(F("MFLN.PROBE"), [](const terminal::CommandContext& ctx) {
if (ctx.argc != 3) {
terminalError(F("[url] [value]"));
terminalError(ctx, F("<url> <value>"));
return;
}
@@ -382,16 +537,17 @@ void _terminalInitCommands() {
client->setInsecure();
if (client->probeMaxFragmentLength(_url.host.c_str(), _url.port, requested_mfln)) {
terminalOK();
} else {
terminalError(F("Buffer size not supported"));
terminalOK(ctx);
return;
}
terminalError(ctx, F("Buffer size not supported"));
});
#endif
terminalRegisterCommand(F("HOST"), [](const terminal::CommandContext& ctx) {
if (ctx.argc != 2) {
terminalError(ctx, F("HOST <hostname>"));
terminalError(ctx, F("<hostname>"));
return;
}
@@ -430,11 +586,11 @@ void _terminalInitCommands() {
void _terminalLoop() {
#if DEBUG_SERIAL_SUPPORT
while (DEBUG_PORT.available()) {
_io.inject(DEBUG_PORT.read());
}
#endif
#if DEBUG_SERIAL_SUPPORT
while (DEBUG_PORT.available()) {
_io.inject(DEBUG_PORT.read());
}
#endif
_terminal.process([](terminal::Terminal::Result result) {
bool out = false;
@@ -623,12 +779,12 @@ void terminalWebApiSetup() {
#endif // TERMINAL_WEB_API_SUPPORT
Stream & terminalDefaultStream() {
Stream& terminalDefaultStream() {
return (Stream &) _io;
}
size_t terminalCapacity() {
return _io.capacity();
return Io::capacity();
}
void terminalInject(void *data, size_t len) {
@@ -644,7 +800,7 @@ void terminalRegisterCommand(const __FlashStringHelper* name, terminal::Terminal
};
void terminalOK(Print& print) {
print.printf_P(PSTR("+%s\n"), "OK");
print.print(F("OK\n"));
}
void terminalError(Print& print, const String& error) {

View File

@@ -31,16 +31,6 @@ void setDefaultHostname() {
}
}
const String& getDevice() {
static const String value(F(DEVICE));
return value;
}
const String& getManufacturer() {
static const String value(F(MANUFACTURER));
return value;
}
String getBoardName() {
return getSetting("boardName", F(DEVICE_NAME));
}
@@ -88,16 +78,26 @@ const String& getCoreRevision() {
return revision;
}
const String& getVersion() {
static const String value {
const char* getVersion() {
static const char version[] PROGMEM {
#if defined(APP_REVISION)
F(APP_VERSION APP_REVISION)
APP_VERSION APP_REVISION
#else
F(APP_VERSION)
APP_VERSION
#endif
};
return value;
return version;
}
const char* getDevice() {
static const char device[] PROGMEM = DEVICE;
return device;
}
const char* getManufacturer() {
static const char manufacturer[] PROGMEM = MANUFACTURER;
return manufacturer;
}
String buildTime() {
@@ -141,219 +141,6 @@ String getUptime() {
#endif // NTP_SUPPORT
// -----------------------------------------------------------------------------
// INFO
// -----------------------------------------------------------------------------
extern "C" uint32_t _SPIFFS_start;
extern "C" uint32_t _SPIFFS_end;
unsigned int info_bytes2sectors(size_t size) {
return (int) (size + SPI_FLASH_SEC_SIZE - 1) / SPI_FLASH_SEC_SIZE;
}
unsigned long info_ota_space() {
return (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
}
unsigned long info_filesystem_space() {
return ((uint32_t)&_SPIFFS_end - (uint32_t)&_SPIFFS_start);
}
void _info_print_memory_layout_line(const char * name, unsigned long bytes, bool reset) {
static unsigned long index = 0;
if (reset) index = 0;
if (0 == bytes) return;
unsigned int _sectors = info_bytes2sectors(bytes);
DEBUG_MSG_P(PSTR("[MAIN] %-20s: %8lu bytes / %4d sectors (%4d to %4d)\n"), name, bytes, _sectors, index, index + _sectors - 1);
index += _sectors;
}
void _info_print_memory_layout_line(const char * name, unsigned long bytes) {
_info_print_memory_layout_line(name, bytes, false);
}
void infoMemory(const char * name, unsigned int total_memory, unsigned int free_memory) {
DEBUG_MSG_P(
PSTR("[MAIN] %-6s: %5u bytes initially | %5u bytes used (%2u%%) | %5u bytes free (%2u%%)\n"),
name,
total_memory,
total_memory - free_memory,
100 * (total_memory - free_memory) / total_memory,
free_memory,
100 * free_memory / total_memory
);
}
void infoMemory(const char* name, const HeapStats& stats) {
infoMemory(name, systemInitialFreeHeap(), stats.available);
}
void infoHeapStats(const char* name, const HeapStats& stats) {
DEBUG_MSG_P(
PSTR("[MAIN] %-6s: %5u contiguous bytes available (%u%% fragmentation)\n"),
name,
stats.usable,
stats.frag_pct
);
}
void infoHeapStats(bool show_frag_stats) {
auto stats = systemHeapStats();
infoMemory("Heap", stats);
if (show_frag_stats) {
infoHeapStats("Heap", stats);
}
}
const char* _info_wifi_sleep_mode(WiFiSleepType_t type) {
switch (type) {
case WIFI_NONE_SLEEP:
return "NONE";
case WIFI_LIGHT_SLEEP:
return "LIGHT";
case WIFI_MODEM_SLEEP:
return "MODEM";
default:
break;
}
return "UNKNOWN";
}
void info(bool first) {
#if DEBUG_SUPPORT
#if DEBUG_LOG_BUFFER_SUPPORT
if (first && debugLogBuffer()) return;
#endif
DEBUG_MSG_P(PSTR("\n\n---8<-------\n\n"));
// -------------------------------------------------------------------------
DEBUG_MSG_P(PSTR("[MAIN] " APP_NAME " %s\n"), getVersion().c_str());
DEBUG_MSG_P(PSTR("[MAIN] " APP_AUTHOR "\n"));
DEBUG_MSG_P(PSTR("[MAIN] " APP_WEBSITE "\n\n"));
DEBUG_MSG_P(PSTR("[MAIN] CPU chip ID: 0x%06X\n"), ESP.getChipId());
DEBUG_MSG_P(PSTR("[MAIN] CPU frequency: %u MHz\n"), ESP.getCpuFreqMHz());
DEBUG_MSG_P(PSTR("[MAIN] SDK version: %s\n"), ESP.getSdkVersion());
DEBUG_MSG_P(PSTR("[MAIN] Core version: %s\n"), getCoreVersion().c_str());
DEBUG_MSG_P(PSTR("[MAIN] Core revision: %s\n"), getCoreRevision().c_str());
DEBUG_MSG_P(PSTR("[MAIN] Built: %s\n"), buildTime().c_str());
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
FlashMode_t mode [[gnu::unused]] = ESP.getFlashChipMode();
DEBUG_MSG_P(PSTR("[MAIN] Flash chip ID: 0x%06X\n"), ESP.getFlashChipId());
DEBUG_MSG_P(PSTR("[MAIN] Flash speed: %u Hz\n"), ESP.getFlashChipSpeed());
DEBUG_MSG_P(PSTR("[MAIN] Flash mode: %s\n"), mode == FM_QIO ? "QIO" : mode == FM_QOUT ? "QOUT" : mode == FM_DIO ? "DIO" : mode == FM_DOUT ? "DOUT" : "UNKNOWN");
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
_info_print_memory_layout_line("Flash size (CHIP)", ESP.getFlashChipRealSize(), true);
_info_print_memory_layout_line("Flash size (SDK)", ESP.getFlashChipSize(), true);
_info_print_memory_layout_line("Reserved", 1 * SPI_FLASH_SEC_SIZE, true);
_info_print_memory_layout_line("Firmware size", ESP.getSketchSize());
_info_print_memory_layout_line("Max OTA size", info_ota_space());
_info_print_memory_layout_line("SPIFFS size", info_filesystem_space());
_info_print_memory_layout_line("EEPROM size", eepromSpace());
_info_print_memory_layout_line("Reserved", 4 * SPI_FLASH_SEC_SIZE);
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
#if SPIFFS_SUPPORT
FSInfo fs_info;
bool fs = SPIFFS.info(fs_info);
if (fs) {
DEBUG_MSG_P(PSTR("[MAIN] SPIFFS total size : %8u bytes / %4d sectors\n"), fs_info.totalBytes, info_bytes2sectors(fs_info.totalBytes));
DEBUG_MSG_P(PSTR("[MAIN] used size : %8u bytes\n"), fs_info.usedBytes);
DEBUG_MSG_P(PSTR("[MAIN] block size : %8u bytes\n"), fs_info.blockSize);
DEBUG_MSG_P(PSTR("[MAIN] page size : %8u bytes\n"), fs_info.pageSize);
DEBUG_MSG_P(PSTR("[MAIN] max files : %8u\n"), fs_info.maxOpenFiles);
DEBUG_MSG_P(PSTR("[MAIN] max length : %8u\n"), fs_info.maxPathLength);
} else {
DEBUG_MSG_P(PSTR("[MAIN] No SPIFFS partition\n"));
}
DEBUG_MSG_P(PSTR("\n"));
#endif
// -------------------------------------------------------------------------
eepromSectorsDebug();
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
infoMemory("EEPROM", SPI_FLASH_SEC_SIZE, SPI_FLASH_SEC_SIZE - settingsSize());
infoHeapStats(!first);
infoMemory("Stack", CONT_STACKSIZE, systemFreeStack());
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
DEBUG_MSG_P(PSTR("[MAIN] Boot version: %d\n"), ESP.getBootVersion());
DEBUG_MSG_P(PSTR("[MAIN] Boot mode: %d\n"), ESP.getBootMode());
auto reason = customResetReason();
if (CustomResetReason::None != reason) {
DEBUG_MSG_P(PSTR("[MAIN] Last reset reason: %s\n"), customResetReasonToPayload(reason).c_str());
} else {
DEBUG_MSG_P(PSTR("[MAIN] Last reset reason: %s\n"), ESP.getResetReason().c_str());
DEBUG_MSG_P(PSTR("[MAIN] Last reset info: %s\n"), ESP.getResetInfo().c_str());
}
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
DEBUG_MSG_P(PSTR("[MAIN] Board: %s\n"), getBoardName().c_str());
DEBUG_MSG_P(PSTR("[MAIN] Support: %s\n"), getEspurnaModules().c_str());
DEBUG_MSG_P(PSTR("[MAIN] OTA: %s\n"), getEspurnaOTAModules().c_str());
#if SENSOR_SUPPORT
DEBUG_MSG_P(PSTR("[MAIN] Sensors: %s\n"), getEspurnaSensors().c_str());
#endif
DEBUG_MSG_P(PSTR("[MAIN] WebUI image: %s\n"), getEspurnaWebUI().c_str());
DEBUG_MSG_P(PSTR("\n"));
// -------------------------------------------------------------------------
if (!first) {
DEBUG_MSG_P(PSTR("[MAIN] Firmware MD5: %s\n"), (char *) ESP.getSketchMD5().c_str());
}
if (ADC_MODE_VALUE == ADC_VCC) {
DEBUG_MSG_P(PSTR("[MAIN] Power: %u mV\n"), ESP.getVcc());
}
if (espurnaLoopDelay()) {
DEBUG_MSG_P(PSTR("[MAIN] Power saving delay value: %lu ms\n"), espurnaLoopDelay());
}
const WiFiSleepType_t sleep_mode = WiFi.getSleepMode();
if (sleep_mode != WIFI_NONE_SLEEP) {
DEBUG_MSG_P(PSTR("[MAIN] WiFi Sleep Mode: %s\n"), _info_wifi_sleep_mode(sleep_mode));
}
// -------------------------------------------------------------------------
#if SYSTEM_CHECK_ENABLED
if (!systemCheck()) {
DEBUG_MSG_P(PSTR("\n"));
DEBUG_MSG_P(PSTR("[MAIN] Device is in SAFE MODE\n"));
}
#endif
// -------------------------------------------------------------------------
DEBUG_MSG_P(PSTR("\n\n---8<-------\n\n"));
#endif // DEBUG_SUPPORT == 1
}
// -----------------------------------------------------------------------------
// SSL
// -----------------------------------------------------------------------------
@@ -529,3 +316,29 @@ size_t hexDecode(const char* in, size_t in_size, uint8_t* out, size_t out_size)
return out_index;
}
const char* getFlashChipMode() {
const char* mode { nullptr };
if (!mode) {
switch (ESP.getFlashChipMode()) {
case FM_QIO:
mode = "QIO";
break;
case FM_QOUT:
mode = "QOUT";
break;
case FM_DIO:
mode = "DIO";
break;
case FM_DOUT:
mode = "DOUT";
break;
case FM_UNKNOWN:
default:
mode = "UNKNOWN";
break;
}
}
return mode;
}

View File

@@ -12,19 +12,19 @@ Copyright (C) 2017-2019 by Xose Pérez <xose dot perez at gmail dot com>
#include "system.h"
#define INLINE inline __attribute__((always_inline))
extern "C" uint32_t _SPIFFS_start;
extern "C" uint32_t _SPIFFS_end;
void setDefaultHostname();
void setBoardName();
const String& getDevice();
const String& getManufacturer();
const String& getCoreVersion();
const String& getCoreRevision();
const String& getVersion();
const char* getFlashChipMode();
const char* getVersion();
const char* getDevice();
const char* getManufacturer();
String getAdminPass();
String getBoardName();
@@ -36,7 +36,6 @@ String getUptime();
void infoHeapStats(const char* name, const HeapStats& stats);
void infoHeapStats(bool show_frag_stats = false);
void infoMemory(const char* name, unsigned int total_memory, unsigned int free_memory);
void info(bool first = false);
bool sslCheckFingerPrint(const char * fingerprint);
bool sslFingerPrintArray(const char * fingerprint, unsigned char * bytearray);

View File

@@ -239,8 +239,8 @@ void _onDiscover(AsyncWebServerRequest *request) {
StaticJsonBuffer<JSON_OBJECT_SIZE(4)> jsonBuffer;
JsonObject &root = jsonBuffer.createObject();
root["app"] = APP_NAME;
root["version"] = getVersion().c_str();
root["device"] = device.c_str();
root["version"] = getVersion();
root["device"] = device;
root["hostname"] = hostname.c_str();
AsyncResponseStream *response = request->beginResponseStream("application/json", root.measureLength() + 1);
@@ -267,7 +267,7 @@ void _onGetConfig(AsyncWebServerRequest *request) {
response->addHeader("X-Frame-Options", "deny");
response->printf("{\n\"app\": \"" APP_NAME "\"");
response->printf(",\n\"version\": \"%s\"", getVersion().c_str());
response->printf(",\n\"version\": \"%s\"", getVersion());
response->printf(",\n\"backup\": \"1\"");
#if NTP_SUPPORT
response->printf(",\n\"timestamp\": \"%s\"", ntpDateTime().c_str());

View File

@@ -1618,7 +1618,7 @@ void init() {
disable();
}
uint8_t stations() {
size_t stations() {
return WiFi.softAPgetStationNum();
}
@@ -2455,6 +2455,14 @@ void wifiApCheck() {
wifi::action(wifi::Action::AccessPointFallbackCheck);
}
size_t wifiApStations() {
if (wifi::ap::enabled()) {
return wifi::ap::stations();
}
return 0;
}
void wifiSetup() {
wifi::internal::init();
wifi::settings::migrate(migrateVersion());

View File

@@ -79,6 +79,7 @@ bool wifiConnected();
// Whether the AP is up and running
bool wifiConnectable();
size_t wifiApStations();
// Current STA connection
String wifiStaSsid();

View File

@@ -256,7 +256,7 @@ void WsDebug::send(bool connected) {
}
bool wsDebugSend(const char* prefix, const char* message) {
if (wifiConnected() && wsConnected()) {
if ((wifiConnected() || wifiApStations()) && wsConnected()) {
_ws_debug.add(prefix, message);
return true;
}
@@ -487,15 +487,15 @@ void _wsOnConnected(JsonObject& root) {
root["webMode"] = WEB_MODE_NORMAL;
root["app_name"] = APP_NAME;
root["app_version"] = getVersion().c_str();
root["app_version"] = getVersion();
root["app_build"] = buildTime();
root["device"] = getDevice().c_str();
root["manufacturer"] = getManufacturer().c_str();
root["device"] = getDevice();
root["manufacturer"] = getManufacturer();
root["chipid"] = getChipId().c_str();
root["mac"] = WiFi.macAddress();
root["mac"] = getFullChipId().c_str();
root["bssid"] = WiFi.BSSIDstr();
root["channel"] = WiFi.channel();
root["hostname"] = getSetting("hostname");
root["hostname"] = getSetting("hostname", getIdentifier());
root["desc"] = getSetting("desc");
root["network"] = wifiStaSsid();
root["deviceip"] = wifiStaIp().toString();