mirror of
https://github.com/xoseperez/espurna.git
synced 2026-03-03 06:54:16 +01:00
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:
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -79,6 +79,7 @@ bool wifiConnected();
|
||||
|
||||
// Whether the AP is up and running
|
||||
bool wifiConnectable();
|
||||
size_t wifiApStations();
|
||||
|
||||
// Current STA connection
|
||||
String wifiStaSsid();
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user