mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-09 22:52:07 +00:00
Cleanup for nodeinfo
This commit is contained in:
parent
01f7cd998a
commit
33cfe14d4a
@ -1704,90 +1704,134 @@ uint16_t Screen::getCompassDiam(uint32_t displayWidth, uint32_t displayHeight)
|
||||
return diam - 20;
|
||||
};
|
||||
|
||||
// *********************
|
||||
// * Node Info *
|
||||
// *********************
|
||||
static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
// We only advance our nodeIndex if the frame # has changed - because
|
||||
// drawNodeInfo will be called repeatedly while the frame is shown
|
||||
display->clear();
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// === Header ===
|
||||
drawCommonHeader(display, x, y);
|
||||
|
||||
// === Reset color in case inverted mode left it BLACK ===
|
||||
display->setColor(WHITE);
|
||||
|
||||
// === Advance to next favorite node when frame changes ===
|
||||
if (state->currentFrame != prevFrame) {
|
||||
prevFrame = state->currentFrame;
|
||||
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB->getNumMeshNodes();
|
||||
meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
if (n->num == nodeDB->getNodeNum()) {
|
||||
// Don't show our node, just skip to next
|
||||
nodeIndex = (nodeIndex + 1) % nodeDB->getNumMeshNodes();
|
||||
n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
}
|
||||
int attempts = 0;
|
||||
int total = nodeDB->getNumMeshNodes();
|
||||
do {
|
||||
nodeIndex = (nodeIndex + 1) % total;
|
||||
meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
if (n && n->is_favorite && n->num != nodeDB->getNodeNum()) {
|
||||
break;
|
||||
}
|
||||
} while (++attempts < total);
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||
if (!node || !node->is_favorite || node->num == nodeDB->getNodeNum()) return;
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
// === Draw Title (centered safe short name or ID) ===
|
||||
static char titleBuf[20];
|
||||
const char *titleStr = nullptr;
|
||||
|
||||
// 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);
|
||||
bool valid = node->has_user && strlen(node->user.short_name) > 0;
|
||||
if (valid) {
|
||||
for (size_t i = 0; i < strlen(node->user.short_name); i++) {
|
||||
uint8_t c = (uint8_t)node->user.short_name[i];
|
||||
if (c < 32 || c > 126) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *username = node->has_user ? node->user.long_name : "Unknown Name";
|
||||
if (valid) {
|
||||
titleStr = node->user.short_name;
|
||||
} else {
|
||||
snprintf(titleBuf, sizeof(titleBuf), "%04X", (uint16_t)(node->num & 0xFFFF));
|
||||
titleStr = titleBuf;
|
||||
}
|
||||
|
||||
const int screenWidth = display->getWidth();
|
||||
const int centerX = x + screenWidth / 2;
|
||||
const int highlightHeight = FONT_HEIGHT_SMALL - 1;
|
||||
const int headerOffsetY = 2;
|
||||
const int titleY = y + headerOffsetY + (highlightHeight - FONT_HEIGHT_SMALL) / 2;
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
display->drawString(centerX, titleY, titleStr);
|
||||
if (config.display.heading_bold) {
|
||||
display->drawString(centerX + 1, titleY, titleStr);
|
||||
}
|
||||
display->setColor(WHITE);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
// === First Row: Last Heard ===
|
||||
static char lastStr[20];
|
||||
screen->getTimeAgoStr(sinceLastSeen(node), lastStr, sizeof(lastStr));
|
||||
display->drawString(x, compactFirstLine, lastStr);
|
||||
|
||||
// === Second Row: Signal / Hops ===
|
||||
static char signalStr[20];
|
||||
|
||||
// section here to choose whether to display hops away rather than signal strength if more than 0 hops away.
|
||||
if (node->hops_away > 0) {
|
||||
snprintf(signalStr, sizeof(signalStr), "Hops Away: %d", node->hops_away);
|
||||
} else {
|
||||
snprintf(signalStr, sizeof(signalStr), "Signal: %d%%", clamp((int)((node->snr + 10) * 5), 0, 100));
|
||||
}
|
||||
display->drawString(x, compactSecondLine, signalStr);
|
||||
|
||||
static char lastStr[20];
|
||||
screen->getTimeAgoStr(sinceLastSeen(node), lastStr, sizeof(lastStr));
|
||||
|
||||
// === Third Row: Distance and Bearing ===
|
||||
static char distStr[20];
|
||||
strncpy(distStr, "? km ?°", sizeof(distStr));
|
||||
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||
strncpy(distStr, "? mi ?°", sizeof(distStr)); // might not have location data
|
||||
} else {
|
||||
strncpy(distStr, "? km ?°", sizeof(distStr));
|
||||
strncpy(distStr, "? mi ?°", sizeof(distStr));
|
||||
}
|
||||
|
||||
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||
const char *fields[] = {username, lastStr, signalStr, distStr, NULL};
|
||||
int16_t compassX = 0, compassY = 0;
|
||||
uint16_t compassDiam = Screen::getCompassDiam(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
|
||||
// coordinates for the center of the compass/circle
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
compassX = x + SCREEN_WIDTH - compassDiam / 2 - 5;
|
||||
compassY = y + SCREEN_HEIGHT / 2;
|
||||
} else {
|
||||
compassX = x + SCREEN_WIDTH - compassDiam / 2 - 5;
|
||||
compassY = y + FONT_HEIGHT_SMALL + (SCREEN_HEIGHT - FONT_HEIGHT_SMALL) / 2;
|
||||
}
|
||||
// === Match GPS screen compass position ===
|
||||
const int16_t topY = compactFirstLine;
|
||||
const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1);
|
||||
const int16_t usableHeight = bottomY - topY - 5;
|
||||
|
||||
int16_t compassRadius = usableHeight / 2;
|
||||
if (compassRadius < 8) compassRadius = 8;
|
||||
const int16_t compassDiam = compassRadius * 2;
|
||||
const int16_t compassX = x + SCREEN_WIDTH - compassRadius - 8;
|
||||
const int16_t compassY = topY + (usableHeight / 2) + ((FONT_HEIGHT_SMALL - 1) / 2) + 2;
|
||||
|
||||
bool hasNodeHeading = false;
|
||||
|
||||
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||
const meshtastic_PositionLite &op = ourNode->position;
|
||||
float myHeading;
|
||||
if (screen->hasHeading())
|
||||
myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians
|
||||
else
|
||||
myHeading = screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
float myHeading = screen->hasHeading()
|
||||
? radians(screen->getHeading())
|
||||
: screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
|
||||
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
||||
|
||||
if (nodeDB->hasValidPosition(node)) {
|
||||
// display direction toward node
|
||||
hasNodeHeading = true;
|
||||
const meshtastic_PositionLite &p = node->position;
|
||||
float d =
|
||||
GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i), DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
|
||||
float bearingToOther =
|
||||
GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i));
|
||||
// If the top of the compass is a static north then bearingToOther can be drawn on the compass directly
|
||||
// If the top of the compass is not a static north we need adjust bearingToOther based on heading
|
||||
float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i),
|
||||
DegD(op.latitude_i), DegD(op.longitude_i));
|
||||
|
||||
float bearingToOther = GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i),
|
||||
DegD(p.latitude_i), DegD(p.longitude_i));
|
||||
|
||||
if (!config.display.compass_north_top)
|
||||
bearingToOther -= myHeading;
|
||||
|
||||
screen->drawNodeHeading(display, compassX, compassY, compassDiam, bearingToOther);
|
||||
|
||||
float bearingToOtherDegrees = (bearingToOther < 0) ? bearingToOther + 2 * PI : bearingToOther;
|
||||
@ -1797,8 +1841,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
if (d < (2 * MILES_TO_FEET))
|
||||
snprintf(distStr, sizeof(distStr), "%.0fft %.0f°", d * METERS_TO_FEET, bearingToOtherDegrees);
|
||||
else
|
||||
snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET,
|
||||
bearingToOtherDegrees);
|
||||
snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET, bearingToOtherDegrees);
|
||||
} else {
|
||||
if (d < 2000)
|
||||
snprintf(distStr, sizeof(distStr), "%.0fm %.0f°", d, bearingToOtherDegrees);
|
||||
@ -1807,20 +1850,17 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
display->drawString(x, compactThirdLine, distStr);
|
||||
|
||||
if (!hasNodeHeading) {
|
||||
// direction to node is unknown so display question mark
|
||||
// Debug info for gps lock errors
|
||||
// LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d", !!ourNode, ourNode && hasValidPosition(ourNode),
|
||||
// hasValidPosition(node));
|
||||
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
|
||||
}
|
||||
display->drawCircle(compassX, compassY, compassDiam / 2);
|
||||
|
||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
// Must be after distStr is populated
|
||||
screen->drawColumns(display, x, y, fields);
|
||||
display->drawCircle(compassX, compassY, compassRadius);
|
||||
|
||||
// === Final reset to WHITE to ensure clean state for next frame ===
|
||||
display->setColor(WHITE);
|
||||
}
|
||||
|
||||
// h! Each node entry holds a reference to its info and how long ago it was heard from
|
||||
|
Loading…
Reference in New Issue
Block a user