mirror of
https://github.com/meshtastic/firmware.git
synced 2025-06-13 16:42: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;
|
return diam - 20;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// *********************
|
||||||
|
// * Node Info *
|
||||||
|
// *********************
|
||||||
static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
{
|
{
|
||||||
// We only advance our nodeIndex if the frame # has changed - because
|
display->clear();
|
||||||
// drawNodeInfo will be called repeatedly while the frame is shown
|
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) {
|
if (state->currentFrame != prevFrame) {
|
||||||
prevFrame = state->currentFrame;
|
prevFrame = state->currentFrame;
|
||||||
|
|
||||||
nodeIndex = (nodeIndex + 1) % nodeDB->getNumMeshNodes();
|
int attempts = 0;
|
||||||
|
int total = nodeDB->getNumMeshNodes();
|
||||||
|
do {
|
||||||
|
nodeIndex = (nodeIndex + 1) % total;
|
||||||
meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
meshtastic_NodeInfoLite *n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
||||||
if (n->num == nodeDB->getNodeNum()) {
|
if (n && n->is_favorite && n->num != nodeDB->getNodeNum()) {
|
||||||
// Don't show our node, just skip to next
|
break;
|
||||||
nodeIndex = (nodeIndex + 1) % nodeDB->getNumMeshNodes();
|
|
||||||
n = nodeDB->getMeshNodeByIndex(nodeIndex);
|
|
||||||
}
|
}
|
||||||
|
} while (++attempts < total);
|
||||||
}
|
}
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(nodeIndex);
|
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
|
bool valid = node->has_user && strlen(node->user.short_name) > 0;
|
||||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
if (valid) {
|
||||||
|
for (size_t i = 0; i < strlen(node->user.short_name); i++) {
|
||||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_INVERTED) {
|
uint8_t c = (uint8_t)node->user.short_name[i];
|
||||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
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];
|
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) {
|
if (node->hops_away > 0) {
|
||||||
snprintf(signalStr, sizeof(signalStr), "Hops Away: %d", node->hops_away);
|
snprintf(signalStr, sizeof(signalStr), "Hops Away: %d", node->hops_away);
|
||||||
} else {
|
} else {
|
||||||
snprintf(signalStr, sizeof(signalStr), "Signal: %d%%", clamp((int)((node->snr + 10) * 5), 0, 100));
|
snprintf(signalStr, sizeof(signalStr), "Signal: %d%%", clamp((int)((node->snr + 10) * 5), 0, 100));
|
||||||
}
|
}
|
||||||
|
display->drawString(x, compactSecondLine, signalStr);
|
||||||
|
|
||||||
static char lastStr[20];
|
// === Third Row: Distance and Bearing ===
|
||||||
screen->getTimeAgoStr(sinceLastSeen(node), lastStr, sizeof(lastStr));
|
|
||||||
|
|
||||||
static char distStr[20];
|
static char distStr[20];
|
||||||
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, "? km ?°", sizeof(distStr));
|
||||||
|
if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) {
|
||||||
|
strncpy(distStr, "? mi ?°", sizeof(distStr));
|
||||||
}
|
}
|
||||||
|
|
||||||
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
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
|
// === Match GPS screen compass position ===
|
||||||
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
const int16_t topY = compactFirstLine;
|
||||||
compassX = x + SCREEN_WIDTH - compassDiam / 2 - 5;
|
const int16_t bottomY = SCREEN_HEIGHT - (FONT_HEIGHT_SMALL - 1);
|
||||||
compassY = y + SCREEN_HEIGHT / 2;
|
const int16_t usableHeight = bottomY - topY - 5;
|
||||||
} else {
|
|
||||||
compassX = x + SCREEN_WIDTH - compassDiam / 2 - 5;
|
int16_t compassRadius = usableHeight / 2;
|
||||||
compassY = y + FONT_HEIGHT_SMALL + (SCREEN_HEIGHT - FONT_HEIGHT_SMALL) / 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;
|
bool hasNodeHeading = false;
|
||||||
|
|
||||||
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
|
if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) {
|
||||||
const meshtastic_PositionLite &op = ourNode->position;
|
const meshtastic_PositionLite &op = ourNode->position;
|
||||||
float myHeading;
|
float myHeading = screen->hasHeading()
|
||||||
if (screen->hasHeading())
|
? radians(screen->getHeading())
|
||||||
myHeading = (screen->getHeading()) * PI / 180; // gotta convert compass degrees to Radians
|
: screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
||||||
else
|
|
||||||
myHeading = screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i));
|
|
||||||
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
screen->drawCompassNorth(display, compassX, compassY, myHeading);
|
||||||
|
|
||||||
if (nodeDB->hasValidPosition(node)) {
|
if (nodeDB->hasValidPosition(node)) {
|
||||||
// display direction toward node
|
|
||||||
hasNodeHeading = true;
|
hasNodeHeading = true;
|
||||||
const meshtastic_PositionLite &p = node->position;
|
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 =
|
float d = GeoCoord::latLongToMeter(DegD(p.latitude_i), DegD(p.longitude_i),
|
||||||
GeoCoord::bearing(DegD(op.latitude_i), DegD(op.longitude_i), DegD(p.latitude_i), DegD(p.longitude_i));
|
DegD(op.latitude_i), DegD(op.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 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)
|
if (!config.display.compass_north_top)
|
||||||
bearingToOther -= myHeading;
|
bearingToOther -= myHeading;
|
||||||
|
|
||||||
screen->drawNodeHeading(display, compassX, compassY, compassDiam, bearingToOther);
|
screen->drawNodeHeading(display, compassX, compassY, compassDiam, bearingToOther);
|
||||||
|
|
||||||
float bearingToOtherDegrees = (bearingToOther < 0) ? bearingToOther + 2 * PI : 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))
|
if (d < (2 * MILES_TO_FEET))
|
||||||
snprintf(distStr, sizeof(distStr), "%.0fft %.0f°", d * METERS_TO_FEET, bearingToOtherDegrees);
|
snprintf(distStr, sizeof(distStr), "%.0fft %.0f°", d * METERS_TO_FEET, bearingToOtherDegrees);
|
||||||
else
|
else
|
||||||
snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET,
|
snprintf(distStr, sizeof(distStr), "%.1fmi %.0f°", d * METERS_TO_FEET / MILES_TO_FEET, bearingToOtherDegrees);
|
||||||
bearingToOtherDegrees);
|
|
||||||
} else {
|
} else {
|
||||||
if (d < 2000)
|
if (d < 2000)
|
||||||
snprintf(distStr, sizeof(distStr), "%.0fm %.0f°", d, bearingToOtherDegrees);
|
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) {
|
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->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->drawCircle(compassX, compassY, compassRadius);
|
||||||
display->setColor(BLACK);
|
|
||||||
}
|
// === Final reset to WHITE to ensure clean state for next frame ===
|
||||||
// Must be after distStr is populated
|
display->setColor(WHITE);
|
||||||
screen->drawColumns(display, x, y, fields);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// h! Each node entry holds a reference to its info and how long ago it was heard from
|
// 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