BaseUI: Select Environmental Data Source (#11209)

* Select Source

* Fixes

* remove per sensor name

---------

Co-authored-by: Thomas Göttgens <tgoettgens@gmail.com>
This commit is contained in:
HarukiToreda
2026-08-05 09:55:18 +00:00
committed by GitHub
co-authored by Thomas Göttgens
parent b59cd58d75
commit 74b9f6ff02
5 files changed
+245 -20

No files matched your search

+130 -20
View File
@@ -142,7 +142,115 @@ extern void drawCommonHeader(OLEDDisplay *display, int16_t x, int16_t y, const c
#include "graphics/ScreenFonts.h"
#include <Throttle.h>
EnvironmentTelemetryModule *environmentTelemetryModule = nullptr;
namespace
{
EnvironmentTelemetryModule::DisplaySource gDisplaySource = EnvironmentTelemetryModule::DisplaySource::Mesh;
} // namespace
static constexpr uint16_t TX_HISTORY_KEY_ENVIRONMENT_TELEMETRY = 0x8002;
static constexpr uint32_t LOCAL_DISPLAY_REFRESH_INTERVAL_MS = 1000;
EnvironmentTelemetryModule::DisplaySource EnvironmentTelemetryModule::getDisplaySource()
{
return gDisplaySource;
}
void EnvironmentTelemetryModule::setDisplaySource(DisplaySource source)
{
gDisplaySource = source;
if (environmentTelemetryModule != nullptr) {
environmentTelemetryModule->lastLocalDisplayRefreshMs = 0;
environmentTelemetryModule->refreshDisplayedMeasurement();
}
}
void EnvironmentTelemetryModule::clearMeasurementPacket()
{
if (lastMeasurementPacket != nullptr) {
packetPool.release(lastMeasurementPacket);
lastMeasurementPacket = nullptr;
}
}
bool EnvironmentTelemetryModule::shouldDisplayRemoteNode(NodeNum nodeNum) const
{
if (nodeNum == 0 || nodeNum == nodeDB->getNodeNum()) {
return false;
}
switch (getDisplaySource()) {
case DisplaySource::LocalSensor:
return false;
case DisplaySource::Mesh:
return true;
case DisplaySource::FavoriteNodesOnly:
return nodeDB->isFavorite(nodeNum);
}
return false;
}
bool EnvironmentTelemetryModule::shouldKeepCurrentRemoteDisplay() const
{
if (lastMeasurementPacket == nullptr) {
return false;
}
return shouldDisplayRemoteNode(getFrom(lastMeasurementPacket));
}
bool EnvironmentTelemetryModule::shouldDisplayLocalMeasurement() const
{
switch (getDisplaySource()) {
case DisplaySource::LocalSensor:
return true;
case DisplaySource::Mesh:
return !shouldKeepCurrentRemoteDisplay();
case DisplaySource::FavoriteNodesOnly:
return false;
}
return false;
}
bool EnvironmentTelemetryModule::refreshLocalMeasurementPacket()
{
meshtastic_Telemetry local = meshtastic_Telemetry_init_zero;
if (!getEnvironmentTelemetry(&local)) {
return false;
}
meshtastic_MeshPacket *localPacket = allocDataProtobuf(local);
if (localPacket == nullptr) {
return false;
}
clearMeasurementPacket();
lastMeasurementPacket = packetPool.allocCopy(*localPacket);
packetPool.release(localPacket);
return lastMeasurementPacket != nullptr;
}
void EnvironmentTelemetryModule::refreshDisplayedMeasurement()
{
if (shouldDisplayLocalMeasurement()) {
if (lastMeasurementPacket != nullptr &&
Throttle::isWithinTimespanMs(lastLocalDisplayRefreshMs, LOCAL_DISPLAY_REFRESH_INTERVAL_MS)) {
return;
}
lastLocalDisplayRefreshMs = millis();
if (!refreshLocalMeasurementPacket()) {
clearMeasurementPacket();
}
return;
}
if (!shouldKeepCurrentRemoteDisplay()) {
clearMeasurementPacket();
}
}
void EnvironmentTelemetryModule::i2cScanFinished(ScanI2C *i2cScanner)
{
@@ -299,6 +407,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = rak9154Sensor.runOnce();
#endif
#endif
refreshDisplayedMeasurement();
}
// it's possible to have this module enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled
@@ -315,6 +424,7 @@ int32_t EnvironmentTelemetryModule::runOnce()
result = delay;
}
}
refreshDisplayedMeasurement();
uint32_t lastTelemetry =
transmitHistory ? transmitHistory->getLastSentToMeshMillis(TX_HISTORY_KEY_ENVIRONMENT_TELEMETRY) : 0;
@@ -411,14 +521,17 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
}
// === First line: Show sender name + time since received (left), and first metric (right) ===
const char *sender = getSenderShortName(*lastMeasurementPacket);
uint32_t agoSecs = service->GetTimeSinceMeshPacket(lastMeasurementPacket);
String agoStr = (agoSecs > 864000) ? "?"
: (agoSecs > 3600) ? String(agoSecs / 3600) + "h"
: (agoSecs > 60) ? String(agoSecs / 60) + "m"
: String(agoSecs) + "s";
String leftStr = String(sender) + " (" + agoStr + ")";
const bool isLocalTelemetry = (getFrom(lastMeasurementPacket) == nodeDB->getNodeNum());
const char *sender = isLocalTelemetry ? "Local Sensor" : getSenderShortName(*lastMeasurementPacket);
String leftStr = String(sender);
if (!isLocalTelemetry) {
uint32_t agoSecs = service->GetTimeSinceMeshPacket(lastMeasurementPacket);
String agoStr = (agoSecs > 864000) ? "?"
: (agoSecs > 3600) ? String(agoSecs / 3600) + "h"
: (agoSecs > 60) ? String(agoSecs / 60) + "m"
: String(agoSecs) + "s";
leftStr += " (" + agoStr + ")";
}
display->drawString(x, currentY, leftStr); // Left side: who and when
// === Collect sensor readings as label strings (no icons) ===
@@ -463,7 +576,7 @@ void EnvironmentTelemetryModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiSt
static uint32_t lastAlertTime = 0;
uint32_t now = millis();
bool isOwnTelemetry = lastMeasurementPacket->from == nodeDB->getNodeNum();
bool isOwnTelemetry = isLocalTelemetry;
bool isCooldownOver = (now - lastAlertTime > 60000);
if (isOwnTelemetry && bannerMsg && isCooldownOver) {
@@ -542,15 +655,17 @@ bool EnvironmentTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPac
LOG_INFO("(Received from %s): radiation=%fµR/h", sender, t->variant.environment_metrics.radiation);
#endif
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
packetPool.release(lastMeasurementPacket);
lastMeasurementPacket = packetPool.allocCopy(mp);
// Cache the latest env metrics per node on NodeDB so the phone can
// pull last-known values across reboots and replays.
nodeDB->updateTelemetry(getFrom(&mp), *t, RX_SRC_RADIO);
const NodeNum senderNode = getFrom(&mp);
if (shouldDisplayRemoteNode(senderNode)) {
clearMeasurementPacket();
lastMeasurementPacket = packetPool.allocCopy(mp);
} else if (!shouldKeepCurrentRemoteDisplay()) {
refreshDisplayedMeasurement();
}
}
return false; // Let others look at this message also if they want
@@ -670,11 +785,6 @@ bool EnvironmentTelemetryModule::sendTelemetry(NodeNum dest, bool phoneOnly)
p->priority = meshtastic_MeshPacket_Priority_RELIABLE;
else
p->priority = meshtastic_MeshPacket_Priority_BACKGROUND;
// release previous packet before occupying a new spot
if (lastMeasurementPacket != nullptr)
packetPool.release(lastMeasurementPacket);
lastMeasurementPacket = packetPool.allocCopy(*p);
if (phoneOnly) {
LOG_INFO("Send packet to phone");
service->sendToPhone(p);