#include "SerialConsole.h" #include "Default.h" #include "NodeDB.h" #include "PowerFSM.h" #include "Throttle.h" #include "configuration.h" #include "time.h" #ifdef RP2040_SLOW_CLOCK #define Port Serial2 #else #ifdef USER_DEBUG_PORT // change by WayenWeng #define Port USER_DEBUG_PORT #else #define Port Serial #endif #endif // Defaulting to the formerly removed phone_timeout_secs value of 15 minutes #define SERIAL_CONNECTION_TIMEOUT (15 * 60) * 1000UL SerialConsole *console; void consoleInit() { new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread DEBUG_PORT.rpInit(); // Simply sets up semaphore } void consolePrintf(const char *format, ...) { va_list arg; va_start(arg, format); console->vprintf(nullptr, format, arg); va_end(arg); console->flush(); } SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), concurrency::OSThread("SerialConsole") { assert(!console); console = this; canWrite = false; // We don't send packets to our port until it has talked to us first #ifdef RP2040_SLOW_CLOCK Port.setTX(SERIAL2_TX); Port.setRX(SERIAL2_RX); #endif Port.begin(SERIAL_BAUD); #if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARCH_RP2040) time_t timeout = millis(); while (!Port) { if (Throttle::isWithinTimespanMs(timeout, FIVE_SECONDS_MS)) { delay(100); } else { break; } } #endif #if !ARCH_PORTDUINO emitRebooted(); #endif } int32_t SerialConsole::runOnce() { return runOncePart(); } void SerialConsole::flush() { Port.flush(); } // For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages bool SerialConsole::checkIsConnected() { return Throttle::isWithinTimespanMs(lastContactMsec, SERIAL_CONNECTION_TIMEOUT); } /** * we override this to notice when we've received a protobuf over the serial * stream. Then we shut off debug serial output. */ bool SerialConsole::handleToRadio(const uint8_t *buf, size_t len) { // only talk to the API once the configuration has been loaded and we're sure the serial port is not disabled. if (config.has_lora && config.security.serial_enabled) { // Switch to protobufs for log messages usingProtobufs = true; canWrite = true; return StreamAPI::handleToRadio(buf, len); } else { return false; } } void SerialConsole::log_to_serial(const char *logLevel, const char *format, va_list arg) { if (usingProtobufs && config.security.debug_log_api_enabled) { meshtastic_LogRecord_Level ll = meshtastic_LogRecord_Level_UNSET; // default to unset switch (logLevel[0]) { case 'D': ll = meshtastic_LogRecord_Level_DEBUG; break; case 'I': ll = meshtastic_LogRecord_Level_INFO; break; case 'W': ll = meshtastic_LogRecord_Level_WARNING; break; case 'E': ll = meshtastic_LogRecord_Level_ERROR; break; case 'C': ll = meshtastic_LogRecord_Level_CRITICAL; break; } auto thread = concurrency::OSThread::currentThread; emitLogRecord(ll, thread ? thread->ThreadName.c_str() : "", format, arg); } else RedirectablePrint::log_to_serial(logLevel, format, arg); }