mirror of
https://github.com/meshtastic/firmware.git
synced 2026-08-03 03:52:45 -04:00
Merge branch 'develop' into indicator-comms
This commit is contained in:
2
.github/workflows/daily_packaging.yml
vendored
2
.github/workflows/daily_packaging.yml
vendored
@@ -35,8 +35,8 @@ jobs:
|
||||
series:
|
||||
- jammy # 22.04 LTS
|
||||
- noble # 24.04 LTS
|
||||
- questing # 25.10
|
||||
- resolute # 26.04 LTS
|
||||
- stonking # 26.10
|
||||
uses: ./.github/workflows/package_ppa.yml
|
||||
with:
|
||||
ppa_repo: ppa:meshtastic/daily
|
||||
|
||||
2
.github/workflows/release_channels.yml
vendored
2
.github/workflows/release_channels.yml
vendored
@@ -23,8 +23,8 @@ jobs:
|
||||
series:
|
||||
- jammy # 22.04 LTS
|
||||
- noble # 24.04 LTS
|
||||
- questing # 25.10
|
||||
- resolute # 26.04 LTS
|
||||
- stonking # 26.10
|
||||
uses: ./.github/workflows/package_ppa.yml
|
||||
with:
|
||||
ppa_repo: |-
|
||||
|
||||
44
.github/workflows/test_native.yml
vendored
44
.github/workflows/test_native.yml
vendored
@@ -7,6 +7,9 @@ on:
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
# Only pushes to the default branch (develop) populate the cache; PR / merge_group runs
|
||||
# restore it but never save, so they stop filling up the repo's Actions cache storage.
|
||||
SAVE_CACHE: ${{ github.event_name == 'push' && github.ref_name == github.event.repository.default_branch }}
|
||||
LCOV_CAPTURE_FLAGS: --quiet --capture --include "${PWD}/src/*" --exclude '*/src/mesh/generated/*' --directory .pio/build/coverage/src --base-directory "${PWD}"
|
||||
|
||||
jobs:
|
||||
@@ -17,7 +20,7 @@ jobs:
|
||||
# check here and fail the PR on a mismatch, keeping the manual count honest.
|
||||
suite-count-check:
|
||||
name: Native Suite Count
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -56,7 +59,7 @@ jobs:
|
||||
|
||||
simulator-tests:
|
||||
name: Native Simulator Tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04-arm
|
||||
needs: suite-count-check
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
@@ -70,10 +73,26 @@ jobs:
|
||||
- name: Install simulator dependencies
|
||||
run: pip install -U dotmap
|
||||
|
||||
- name: Restore PlatformIO cache
|
||||
id: pio-cache
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-simulator-tests-${{ hashFiles('platformio.ini', 'variants/native/portduino.ini', 'variants/native/portduino/platformio.ini') }}
|
||||
restore-keys: |
|
||||
pio-simulator-tests-
|
||||
|
||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||
- name: Build for native/coverage
|
||||
run: platformio run -e coverage
|
||||
|
||||
- name: Save PlatformIO cache
|
||||
if: env.SAVE_CACHE == 'true' && steps.pio-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v6
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-simulator-tests-${{ hashFiles('platformio.ini', 'variants/native/portduino.ini', 'variants/native/portduino/platformio.ini') }}
|
||||
|
||||
- name: Capture initial coverage information
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -139,7 +158,7 @@ jobs:
|
||||
|
||||
platformio-tests:
|
||||
name: Native PlatformIO Tests
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04-arm
|
||||
needs: suite-count-check
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
@@ -159,11 +178,27 @@ jobs:
|
||||
- name: Disable BUILD_EPOCH
|
||||
run: sed -i 's/-DBUILD_EPOCH=$UNIX_TIME/#-DBUILD_EPOCH=$UNIX_TIME/' platformio.ini
|
||||
|
||||
- name: Restore PlatformIO cache
|
||||
id: pio-cache
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-coverage-tests-${{ hashFiles('platformio.ini', 'variants/native/portduino.ini', 'variants/native/portduino/platformio.ini') }}
|
||||
restore-keys: |
|
||||
pio-coverage-tests-
|
||||
|
||||
- name: Build test programs once
|
||||
# One shared build of src + every test program. This is the single source build; gcov then
|
||||
# accumulates coverage counts into this shared .pio/build/coverage/src as the chunks run.
|
||||
run: platformio test -e coverage --without-testing
|
||||
|
||||
- name: Save PlatformIO cache
|
||||
if: env.SAVE_CACHE == 'true' && steps.pio-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v6
|
||||
with:
|
||||
path: ~/.platformio/.cache
|
||||
key: pio-coverage-tests-${{ hashFiles('platformio.ini', 'variants/native/portduino.ini', 'variants/native/portduino/platformio.ini') }}
|
||||
|
||||
- name: Run tests one area at a time
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -270,7 +305,8 @@ jobs:
|
||||
needs:
|
||||
- simulator-tests
|
||||
- platformio-tests
|
||||
if: always()
|
||||
# Run this job even if the previous jobs failed, but skip if the workflow was cancelled.
|
||||
if: ${{ !cancelled() }}
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||
|
||||
|
||||
@@ -1467,7 +1467,7 @@ void Screen::setFrames(FrameFocus focus)
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
if (!hiddenFrames.wifi && isWifiAvailable()) {
|
||||
fsi.positions.wifi = numframes;
|
||||
normalFrames[numframes++] = graphics::DebugRenderer::drawDebugInfoWiFiTrampoline;
|
||||
normalFrames[numframes++] = graphics::DebugRenderer::drawFrameWiFi;
|
||||
indicatorIcons.push_back(icon_wifi);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -195,27 +195,6 @@ enum class FrameDirection { NEXT, PREVIOUS };
|
||||
// Forward declarations
|
||||
class Screen;
|
||||
|
||||
/// Handles gathering and displaying debug information.
|
||||
class DebugInfo
|
||||
{
|
||||
public:
|
||||
DebugInfo(const DebugInfo &) = delete;
|
||||
DebugInfo &operator=(const DebugInfo &) = delete;
|
||||
|
||||
private:
|
||||
friend Screen;
|
||||
|
||||
DebugInfo() {}
|
||||
|
||||
/// Renders the debug screen.
|
||||
void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
/// Protects all of internal state.
|
||||
concurrency::Lock lock;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This class deals with showing things on the screen of the device.
|
||||
*
|
||||
@@ -647,11 +626,6 @@ class Screen : public concurrency::OSThread
|
||||
// stick to standard EASCII codes)
|
||||
}
|
||||
|
||||
/// Returns a handle to the DebugInfo screen.
|
||||
//
|
||||
// Use this handle to set things like battery status, user count, GPS status, etc.
|
||||
DebugInfo *debug_info() { return &debugInfo; }
|
||||
|
||||
// Handle observer events
|
||||
int handleStatusUpdate(const meshtastic::Status *arg);
|
||||
int handleUIFrameEvent(const UIFrameEvent *arg);
|
||||
@@ -824,9 +798,6 @@ class Screen : public concurrency::OSThread
|
||||
float compassHeading;
|
||||
uint32_t endCalibrationAt;
|
||||
|
||||
/// Holds state for debug information
|
||||
DebugInfo debugInfo;
|
||||
|
||||
/// Display device
|
||||
#ifdef USE_ST7789
|
||||
ST7789Spi *dispdev;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "FSCommon.h"
|
||||
#include "MeshService.h"
|
||||
#include "NodeDB.h"
|
||||
#include "Throttle.h"
|
||||
#include "UIRenderer.h"
|
||||
#include "airtime.h"
|
||||
#include "gps/RTC.h"
|
||||
@@ -16,9 +15,6 @@
|
||||
#include "graphics/TimeFormatters.h"
|
||||
#include "graphics/images.h"
|
||||
#include "main.h"
|
||||
#include "mesh/Channels.h"
|
||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||
#include "sleep.h"
|
||||
|
||||
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
|
||||
#include "mesh/wifi/WiFiAPClient.h"
|
||||
@@ -28,9 +24,6 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "modules/StoreForwardModule.h"
|
||||
#endif
|
||||
#include <DisplayFormatters.h>
|
||||
#include <RadioLibInterface.h>
|
||||
#include <target_specific.h>
|
||||
@@ -39,111 +32,17 @@ using namespace meshtastic;
|
||||
|
||||
// External variables
|
||||
extern std::unique_ptr<graphics::Screen> screen;
|
||||
extern PowerStatus *powerStatus;
|
||||
extern NodeStatus *nodeStatus;
|
||||
extern GPSStatus *gpsStatus;
|
||||
extern Channels channels;
|
||||
extern AirTime *airTime;
|
||||
|
||||
// External functions from Screen.cpp
|
||||
extern bool heartbeat;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
extern StoreForwardModule *storeForwardModule;
|
||||
#endif
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
namespace DebugRenderer
|
||||
{
|
||||
|
||||
void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
char channelStr[20];
|
||||
snprintf(channelStr, sizeof(channelStr), "#%s", channels.getName(channels.getPrimaryIndex()));
|
||||
// Display nodes status
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
UIRenderer::drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
|
||||
} else {
|
||||
UIRenderer::drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
|
||||
}
|
||||
#if HAS_GPS
|
||||
// Display GPS status
|
||||
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
|
||||
UIRenderer::drawGpsPowerStatus(display, x, y + 2, gpsStatus);
|
||||
} else {
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
UIRenderer::drawGps(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
|
||||
} else {
|
||||
UIRenderer::drawGps(display, x + (SCREEN_WIDTH * 0.63), y + 3, gpsStatus);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
display->setColor(WHITE);
|
||||
// Draw the channel name
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
|
||||
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
|
||||
if (moduleConfig.store_forward.enabled) {
|
||||
#ifdef ARCH_ESP32
|
||||
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
|
||||
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
|
||||
#if (defined(USE_EINK) || defined(HAS_SPI_TFT) || ARCH_PORTDUINO) && !defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12,
|
||||
8, imgQuestionL1);
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 11 + FONT_HEIGHT_SMALL, 12,
|
||||
8, imgQuestionL2);
|
||||
#else
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(screen->ourId), y + 2 + FONT_HEIGHT_SMALL, 8,
|
||||
8, imgQuestion);
|
||||
#endif
|
||||
} else {
|
||||
#if (defined(USE_EINK) || defined(HAS_SPI_TFT)) && !defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 16,
|
||||
8, imgSFL1);
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 11 + FONT_HEIGHT_SMALL, 16,
|
||||
8, imgSFL2);
|
||||
#else
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(screen->ourId), y + 2 + FONT_HEIGHT_SMALL, 11,
|
||||
8, imgSF);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// TODO: Raspberry Pi supports more than just the one screen size
|
||||
#if (defined(USE_EINK) || defined(HAS_SPI_TFT) || ARCH_PORTDUINO) && !defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgInfoL1);
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8,
|
||||
imgInfoL2);
|
||||
#else
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(screen->ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8,
|
||||
imgInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(screen->ourId), y + FONT_HEIGHT_SMALL, screen->ourId);
|
||||
|
||||
// Draw any log messages
|
||||
display->drawLogBuffer(x, y + (FONT_HEIGHT_SMALL * 2));
|
||||
|
||||
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
|
||||
#ifdef SHOW_REDRAWS
|
||||
if (heartbeat)
|
||||
display->setPixel(0, 0);
|
||||
heartbeat = !heartbeat;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ****************************
|
||||
// * WiFi Screen *
|
||||
// ****************************
|
||||
@@ -230,12 +129,6 @@ void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, i
|
||||
#endif
|
||||
}
|
||||
|
||||
// Trampoline functions for DebugInfo class access
|
||||
void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
drawFrameWiFi(display, state, x, y);
|
||||
}
|
||||
|
||||
// ****************************
|
||||
// * LoRa Focused Screen *
|
||||
// ****************************
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace graphics
|
||||
|
||||
/// Forward declarations
|
||||
class Screen;
|
||||
class DebugInfo;
|
||||
|
||||
/**
|
||||
* @brief Debug and diagnostic drawing functions
|
||||
@@ -18,13 +17,9 @@ class DebugInfo;
|
||||
*/
|
||||
namespace DebugRenderer
|
||||
{
|
||||
// Debug frame functions
|
||||
void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
// WiFi status display
|
||||
void drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
// Trampoline functions for framework callback compatibility
|
||||
void drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
// LoRa information display
|
||||
void drawLoRaFocused(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
|
||||
|
||||
|
||||
@@ -547,22 +547,6 @@ void UIRenderer::drawGps(OLEDDisplay *display, int16_t x, int16_t y, const mesht
|
||||
}
|
||||
}
|
||||
|
||||
// Draw status when GPS is disabled or not present
|
||||
void UIRenderer::drawGpsPowerStatus(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gps)
|
||||
{
|
||||
const char *displayLine;
|
||||
int pos;
|
||||
if (y < FONT_HEIGHT_SMALL) { // Line 1: use short string
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off";
|
||||
pos = display->getWidth() - display->getStringWidth(displayLine);
|
||||
} else {
|
||||
displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "GPS not present"
|
||||
: "GPS is disabled";
|
||||
pos = (display->getWidth() - display->getStringWidth(displayLine)) / 2;
|
||||
}
|
||||
display->drawString(x + pos, y, displayLine);
|
||||
}
|
||||
|
||||
void UIRenderer::drawGpsAltitude(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gps)
|
||||
{
|
||||
char displayLine[32];
|
||||
|
||||
@@ -42,7 +42,6 @@ class UIRenderer
|
||||
static void drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus,
|
||||
const char *mode = "line1");
|
||||
static void drawGpsAltitude(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
|
||||
static void drawGpsPowerStatus(OLEDDisplay *display, int16_t x, int16_t y, const meshtastic::GPSStatus *gpsStatus);
|
||||
|
||||
// Overlay and special screens
|
||||
static void drawFrameText(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y, const char *text);
|
||||
|
||||
@@ -29,21 +29,6 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
|
||||
0xf3, 0x3f, 0x33, 0x30, 0x33, 0x33, 0x33, 0x33, 0x03, 0x33, 0xff, 0x33,
|
||||
0xfe, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0x3f, 0xe0, 0x1f};
|
||||
|
||||
#if (defined(USE_EINK) || defined(HAS_SPI_TFT) || ARCH_PORTDUINO) && !defined(DISPLAY_FORCE_SMALL_FONTS)
|
||||
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
|
||||
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||
const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff};
|
||||
const uint8_t imgInfoL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
|
||||
const uint8_t imgSFL1[] PROGMEM = {0xb6, 0x8f, 0x19, 0x11, 0x31, 0xe3, 0xc2, 0x01,
|
||||
0x01, 0xf9, 0xf9, 0x89, 0x89, 0x89, 0x09, 0xeb};
|
||||
const uint8_t imgSFL2[] PROGMEM = {0x0e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08,
|
||||
0x00, 0x0f, 0x0f, 0x00, 0x08, 0x08, 0x08, 0x0f};
|
||||
#else
|
||||
const uint8_t imgInfo[] PROGMEM = {0xff, 0x81, 0x00, 0xfb, 0xfb, 0x00, 0x81, 0xff};
|
||||
const uint8_t imgQuestion[] PROGMEM = {0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1, 0xdf};
|
||||
const uint8_t imgSF[] PROGMEM = {0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
|
||||
#endif
|
||||
|
||||
// === Horizontal battery ===
|
||||
// Basic battery design and all related pieces
|
||||
const unsigned char batteryBitmap_h_bottom[] PROGMEM = {
|
||||
|
||||
Reference in New Issue
Block a user