diff --git a/protobufs b/protobufs index a3030d5ff..57ddb288e 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit a3030d5ff187091c9fbbd08dd797cca5085736fe +Subproject commit 57ddb288e87438db3b5b99aa61f66a354c47bffb diff --git a/src/AccelerometerThread.h b/src/AccelerometerThread.h index 0f04de057..39ae90385 100644 --- a/src/AccelerometerThread.h +++ b/src/AccelerometerThread.h @@ -288,7 +288,7 @@ class AccelerometerThread : public concurrency::OSThread compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2; } display->drawCircle(compassX, compassY, getCompassDiam(display) / 2); - drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180); + screen->drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180); } #endif }; diff --git a/src/RedirectablePrint.cpp b/src/RedirectablePrint.cpp index b77720d85..265bb42d6 100644 --- a/src/RedirectablePrint.cpp +++ b/src/RedirectablePrint.cpp @@ -50,7 +50,7 @@ size_t RedirectablePrint::write(uint8_t c) // serial port said (which could be zero) } -size_t RedirectablePrint::vprintf(const char *format, va_list arg) +size_t RedirectablePrint::vprintf(const char *logLevel, const char *format, va_list arg) { va_list copy; static char printBuf[160]; @@ -66,25 +66,39 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg) len = sizeof(printBuf) - 1; printBuf[sizeof(printBuf) - 2] = '\n'; } - + for (size_t f = 0; f < len; f++) { + if (!std::isprint(static_cast(printBuf[f])) && printBuf[f] != '\n') + printBuf[f] = '#'; + } + if (logLevel != nullptr) { + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) + Print::write("\u001b[34m", 6); + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) + Print::write("\u001b[32m", 6); + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) + Print::write("\u001b[33m", 6); + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0) + Print::write("\u001b[31m", 6); + } len = Print::write(printBuf, len); + Print::write("\u001b[0m", 5); return len; } -size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) +void RedirectablePrint::log(const char *logLevel, const char *format, ...) { #ifdef ARCH_PORTDUINO if (settingsMap[logoutputlevel] < level_debug && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) - return 0; + return; else if (settingsMap[logoutputlevel] < level_info && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) - return 0; + return; else if (settingsMap[logoutputlevel] < level_warn && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) - return 0; + return; #endif if (moduleConfig.serial.override_console_serial_port && strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) { - return 0; + return; } - size_t r = 0; + #ifdef HAS_FREE_RTOS if (inDebugPrint != nullptr && xSemaphoreTake(inDebugPrint, portMAX_DELAY) == pdTRUE) { #else @@ -100,6 +114,14 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) // If we are the first message on a report, include the header if (!isContinuationMessage) { + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_DEBUG) == 0) + Print::write("\u001b[34m", 6); + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_INFO) == 0) + Print::write("\u001b[32m", 6); + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_WARN) == 0) + Print::write("\u001b[33m", 6); + if (strcmp(logLevel, MESHTASTIC_LOG_LEVEL_ERROR) == 0) + Print::write("\u001b[31m", 6); uint32_t rtc_sec = getValidTime(RTCQuality::RTCQualityDevice, true); // display local time on logfile if (rtc_sec > 0) { long hms = rtc_sec % SEC_PER_DAY; @@ -113,15 +135,15 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN; int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN #ifdef ARCH_PORTDUINO - r += ::printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); + ::printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); #else - r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); + printf("%s \u001b[0m| %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000); #endif } else #ifdef ARCH_PORTDUINO - r += ::printf("%s | ??:??:?? %u ", logLevel, millis() / 1000); + ::printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000); #else - r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000); + printf("%s \u001b[0m| ??:??:?? %u ", logLevel, millis() / 1000); #endif auto thread = concurrency::OSThread::currentThread; @@ -133,7 +155,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) print("] "); } } - r += vprintf(format, arg); + vprintf(logLevel, format, arg); #if (HAS_WIFI || HAS_ETHERNET) && !defined(ARCH_PORTDUINO) // if syslog is in use, collect the log messages and send them to syslog @@ -211,7 +233,7 @@ size_t RedirectablePrint::log(const char *logLevel, const char *format, ...) #endif } - return r; + return; } void RedirectablePrint::hexDump(const char *logLevel, unsigned char *buf, uint16_t len) diff --git a/src/RedirectablePrint.h b/src/RedirectablePrint.h index 31cc1b6ef..a29ad9c74 100644 --- a/src/RedirectablePrint.h +++ b/src/RedirectablePrint.h @@ -41,10 +41,10 @@ class RedirectablePrint : public Print * log message. Otherwise we assume more prints will come before the log message ends. This * allows you to call logDebug a few times to build up a single log message line if you wish. */ - size_t log(const char *logLevel, const char *format, ...) __attribute__((format(printf, 3, 4))); + void log(const char *logLevel, const char *format, ...) __attribute__((format(printf, 3, 4))); /** like printf but va_list based */ - size_t vprintf(const char *format, va_list arg); + size_t vprintf(const char *logLevel, const char *format, va_list arg); void hexDump(const char *logLevel, unsigned char *buf, uint16_t len); diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 53ece0fa3..41064f288 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -24,7 +24,7 @@ void consolePrintf(const char *format, ...) { va_list arg; va_start(arg, format); - console->vprintf(format, arg); + console->vprintf(nullptr, format, arg); va_end(arg); console->flush(); } diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 8c6146efb..47a56b2b0 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -79,7 +79,6 @@ namespace graphics // A text message frame + debug frame + all the node infos FrameCallback *normalFrames; static uint32_t targetFramerate = IDLE_FRAMERATE; -static char btPIN[16] = "888888"; uint32_t logo_timeout = 5000; // 4 seconds for EACH logo @@ -229,7 +228,7 @@ static void drawOEMBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, i drawOEMIconScreen(region, display, state, x, y); } -static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message) +void Screen::drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *message) { uint16_t x_offset = display->width() / 2; display->setTextAlignment(TEXT_ALIGN_CENTER); @@ -237,19 +236,6 @@ static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16 display->drawString(x_offset + x, 26 + y, message); } -static void drawBootScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -{ -#ifdef ARCH_ESP32 - if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) { - drawFrameText(display, state, x, y, "Resuming..."); - } else -#endif - { - const char *region = myRegion ? myRegion->name : NULL; - drawIconScreen(region, display, state, x, y); - } -} - // Used on boot when a certificate is being created static void drawSSLScreen(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) { @@ -1336,32 +1322,10 @@ static void drawNodeHeading(OLEDDisplay *display, int16_t compassX, int16_t comp arrowPoints[i]->scale(getCompassDiam(display) * 0.6); arrowPoints[i]->translate(compassX, compassY); } - drawLine(display, tip, tail); - drawLine(display, leftArrow, tip); - drawLine(display, rightArrow, tip); + display->drawLine(tip.x, tip.y, tail.x, tail.y); + display->drawLine(leftArrow.x, leftArrow.y, tip.x, tip.y); + display->drawLine(rightArrow.x, rightArrow.y, tip.x, tip.y); } -/* -// Draw north -static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading) -{ - // If north is supposed to be at the top of the compass we want rotation to be +0 - if (config.display.compass_north_top) - myHeading = -0; - - Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f); - Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f); - Point *rosePoints[] = {&N1, &N2, &N3, &N4}; - - for (int i = 0; i < 4; i++) { - // North on compass will be negative of heading - rosePoints[i]->rotate(-myHeading); - rosePoints[i]->scale(getCompassDiam(display)); - rosePoints[i]->translate(compassX, compassY); - } - drawLine(display, N1, N3); - drawLine(display, N2, N4); - drawLine(display, N1, N4); -}*/ // Get a string representation of the time passed since something happened static void getTimeAgoStr(uint32_t agoSecs, char *timeStr, uint8_t maxLength) @@ -1461,7 +1425,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians else myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); - drawCompassNorth(display, compassX, compassY, myHeading); + screen->drawCompassNorth(display, compassX, compassY, myHeading); if (hasValidPosition(node)) { // display direction toward node @@ -1562,7 +1526,7 @@ static void drawWaypointFrame(OLEDDisplay *display, OLEDDisplayUiState *state, i myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians else myHeading = estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); - drawCompassNorth(display, compassX, compassY, myHeading); + screen->drawCompassNorth(display, compassX, compassY, myHeading); // Distance to Waypoint float d = GeoCoord::latLongToMeter(DegD(wp.latitude_i), DegD(wp.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i)); @@ -1758,9 +1722,19 @@ void Screen::setup() // Add frames. EINK_ADD_FRAMEFLAG(dispdev, DEMAND_FAST); - static FrameCallback bootFrames[] = {drawBootScreen}; - static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]); - ui->setFrames(bootFrames, bootFrameCount); + alertFrames[0] = [this](OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) -> void { +#ifdef ARCH_ESP32 + if (wakeCause == ESP_SLEEP_WAKEUP_TIMER || wakeCause == ESP_SLEEP_WAKEUP_EXT1) { + drawFrameText(display, state, x, y, "Resuming..."); + } else +#endif + { + // Draw region in upper left + const char *region = myRegion ? myRegion->name : NULL; + drawIconScreen(region, display, state, x, y); + } + }; + ui->setFrames(alertFrames, 1); // No overlays. ui->setOverlays(nullptr, 0); @@ -2723,4 +2697,4 @@ int Screen::handleWaypoint(const meshtastic_MeshPacket *arg) } // namespace graphics #else graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} -#endif // HAS_SCREEN +#endif // HAS_SCREEN \ No newline at end of file diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 2029fc163..eba7f2678 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -86,6 +86,68 @@ class Screen #define SEGMENT_WIDTH 16 #define SEGMENT_HEIGHT 4 +namespace +{ +/// A basic 2D point class for drawing +class Point +{ + public: + float x, y; + + Point(float _x, float _y) : x(_x), y(_y) {} + + /// Apply a rotation around zero (standard rotation matrix math) + void rotate(float radian) + { + float cos = cosf(radian), sin = sinf(radian); + float rx = x * cos + y * sin, ry = -x * sin + y * cos; + + x = rx; + y = ry; + } + + void translate(int16_t dx, int dy) + { + x += dx; + y += dy; + } + + void scale(float f) + { + // We use -f here to counter the flip that happens + // on the y axis when drawing and rotating on screen + x *= f; + y *= -f; + } +}; + +} // namespace + +static uint16_t getCompassDiam(OLEDDisplay *display) +{ + uint16_t diam = 0; + uint16_t offset = 0; + + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) + offset = FONT_HEIGHT_SMALL; + + // get the smaller of the 2 dimensions and subtract 20 + if (display->getWidth() > (display->getHeight() - offset)) { + diam = display->getHeight() - offset; + // if 2/3 of the other size would be smaller, use that + if (diam > (display->getWidth() * 2 / 3)) { + diam = display->getWidth() * 2 / 3; + } + } else { + diam = display->getWidth(); + if (diam > ((display->getHeight() - offset) * 2 / 3)) { + diam = (display->getHeight() - offset) * 2 / 3; + } + } + + return diam - 20; +}; + namespace graphics { @@ -172,6 +234,30 @@ class Screen : public concurrency::OSThread void blink(); + void drawFrameText(OLEDDisplay *, OLEDDisplayUiState *, int16_t, int16_t, const char *); + + // Draw north + void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading) + { + // If north is supposed to be at the top of the compass we want rotation to be +0 + if (config.display.compass_north_top) + myHeading = -0; + + Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f); + Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f); + Point *rosePoints[] = {&N1, &N2, &N3, &N4}; + + for (int i = 0; i < 4; i++) { + // North on compass will be negative of heading + rosePoints[i]->rotate(-myHeading); + rosePoints[i]->scale(getCompassDiam(display)); + rosePoints[i]->translate(compassX, compassY); + } + display->drawLine(N1.x, N1.y, N3.x, N3.y); + display->drawLine(N2.x, N2.y, N4.x, N4.y); + display->drawLine(N1.x, N1.y, N4.x, N4.y); + } + /// Handle button press, trackball or swipe action) void onPress() { enqueueCmd(ScreenCmd{.cmd = Cmd::ON_PRESS}); } void showPrevFrame() { enqueueCmd(ScreenCmd{.cmd = Cmd::SHOW_PREV_FRAME}); } @@ -457,92 +543,5 @@ class Screen : public concurrency::OSThread }; } // namespace graphics -namespace -{ -/// A basic 2D point class for drawing -class Point -{ - public: - float x, y; - Point(float _x, float _y) : x(_x), y(_y) {} - - /// Apply a rotation around zero (standard rotation matrix math) - void rotate(float radian) - { - float cos = cosf(radian), sin = sinf(radian); - float rx = x * cos + y * sin, ry = -x * sin + y * cos; - - x = rx; - y = ry; - } - - void translate(int16_t dx, int dy) - { - x += dx; - y += dy; - } - - void scale(float f) - { - // We use -f here to counter the flip that happens - // on the y axis when drawing and rotating on screen - x *= f; - y *= -f; - } -}; - -} // namespace - -static void drawLine(OLEDDisplay *d, const Point &p1, const Point &p2) -{ - d->drawLine(p1.x, p1.y, p2.x, p2.y); -} - -static uint16_t getCompassDiam(OLEDDisplay *display) -{ - uint16_t diam = 0; - uint16_t offset = 0; - - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) - offset = FONT_HEIGHT_SMALL; - - // get the smaller of the 2 dimensions and subtract 20 - if (display->getWidth() > (display->getHeight() - offset)) { - diam = display->getHeight() - offset; - // if 2/3 of the other size would be smaller, use that - if (diam > (display->getWidth() * 2 / 3)) { - diam = display->getWidth() * 2 / 3; - } - } else { - diam = display->getWidth(); - if (diam > ((display->getHeight() - offset) * 2 / 3)) { - diam = (display->getHeight() - offset) * 2 / 3; - } - } - - return diam - 20; -}; - -// Draw north -static void drawCompassNorth(OLEDDisplay *display, int16_t compassX, int16_t compassY, float myHeading) -{ - // If north is supposed to be at the top of the compass we want rotation to be +0 - if (config.display.compass_north_top) - myHeading = -0; - - Point N1(-0.04f, 0.65f), N2(0.04f, 0.65f); - Point N3(-0.04f, 0.55f), N4(0.04f, 0.55f); - Point *rosePoints[] = {&N1, &N2, &N3, &N4}; - - for (int i = 0; i < 4; i++) { - // North on compass will be negative of heading - rosePoints[i]->rotate(-myHeading); - rosePoints[i]->scale(getCompassDiam(display)); - rosePoints[i]->translate(compassX, compassY); - } - drawLine(display, N1, N3); - drawLine(display, N2, N4); - drawLine(display, N1, N4); -} #endif \ No newline at end of file diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 2da4b86e6..e3037c910 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -22,7 +22,6 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { The wifi radio and the oled screen will be put to sleep. This mode may still potentially have higher power usage due to it's preference in message rebroadcasting on the mesh. */ meshtastic_Config_DeviceConfig_Role_ROUTER = 2, - /* Description: Combination of both ROUTER and CLIENT. Not for mobile devices. */ meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3, /* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list. Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry