mirror of
https://github.com/meshtastic/firmware.git
synced 2026-11-07 14:54:44 -05:00
NodeDB: hold environment satellites protobuf-encoded
Each environment satellite held a full meshtastic_EnvironmentMetrics, 304 B for 38 optional fields, of which a real sensor sets a handful. At the nRF52 cap of 40 that is ~12 KB of heap holding about 1 KB of data. Store the encoded bytes instead (~15-40 B per entry) and decode on read: copyNodeEnvironment() keeps its signature. The save writes the stored bytes straight out as the entry's environment_metrics, so nodes.proto is unchanged; the load packs each decoded entry. hasNodeEnvironment() becomes a key lookup, and MemAudit counts the real blob sizes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f8d60d82a9
commit
ebda44c677
3 files changed
+156
-20
No files matched your search
+61
-14
@@ -253,7 +253,7 @@ std::map<NodeNum, meshtastic_PositionLite> *s_decodePositionsTarget = nullptr;
|
||||
std::map<NodeNum, meshtastic_DeviceMetrics> *s_decodeTelemetryTarget = nullptr;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
std::map<NodeNum, meshtastic_EnvironmentMetrics> *s_decodeEnvironmentTarget = nullptr;
|
||||
std::map<NodeNum, PackedEnvironmentMetrics> *s_decodeEnvironmentTarget = nullptr;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_STATUSDB
|
||||
std::map<NodeNum, meshtastic_StatusMessage> *s_decodeStatusTarget = nullptr;
|
||||
@@ -268,7 +268,7 @@ const std::map<NodeNum, meshtastic_PositionLite> *s_encodePositionsSource = null
|
||||
const std::map<NodeNum, meshtastic_DeviceMetrics> *s_encodeTelemetrySource = nullptr;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
const std::map<NodeNum, meshtastic_EnvironmentMetrics> *s_encodeEnvironmentSource = nullptr;
|
||||
const std::map<NodeNum, PackedEnvironmentMetrics> *s_encodeEnvironmentSource = nullptr;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_STATUSDB
|
||||
const std::map<NodeNum, meshtastic_StatusMessage> *s_encodeStatusSource = nullptr;
|
||||
@@ -293,6 +293,18 @@ template <typename Entry, typename Value, typename Fill>
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
// One NodeEnvironmentEntry body: num, then the stored environment_metrics bytes as-is (what pb_encode would write)
|
||||
bool encodePackedEnvironmentEntryBody(pb_ostream_t *ostream, NodeNum num, const PackedEnvironmentMetrics &packed)
|
||||
{
|
||||
if (num &&
|
||||
(!pb_encode_tag(ostream, PB_WT_VARINT, meshtastic_NodeEnvironmentEntry_num_tag) || !pb_encode_varint(ostream, num)))
|
||||
return false;
|
||||
return pb_encode_tag(ostream, PB_WT_STRING, meshtastic_NodeEnvironmentEntry_environment_metrics_tag) &&
|
||||
pb_encode_string(ostream, packed.bytes.data(), packed.bytes.size());
|
||||
}
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
bool meshtastic_NodeDatabase_callback(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_t *field)
|
||||
@@ -442,14 +454,16 @@ bool meshtastic_NodeDatabase_callback(pb_istream_t *istream, pb_ostream_t *ostre
|
||||
case meshtastic_NodeDatabase_environment_tag: {
|
||||
if (ostream) {
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
if (s_encodeEnvironmentSource)
|
||||
return encodeSatelliteMap<meshtastic_NodeEnvironmentEntry>(
|
||||
ostream, iter, meshtastic_NodeEnvironmentEntry_fields, *s_encodeEnvironmentSource,
|
||||
[](meshtastic_NodeEnvironmentEntry &e, NodeNum num, const meshtastic_EnvironmentMetrics &v) {
|
||||
e.num = num;
|
||||
e.has_environment_metrics = true;
|
||||
e.environment_metrics = v;
|
||||
});
|
||||
if (s_encodeEnvironmentSource) {
|
||||
for (const auto &kv : *s_encodeEnvironmentSource) {
|
||||
pb_ostream_t sizing = PB_OSTREAM_SIZING;
|
||||
if (!encodePackedEnvironmentEntryBody(&sizing, kv.first, kv.second) ||
|
||||
!pb_encode_tag_for_field(ostream, iter) || !pb_encode_varint(ostream, sizing.bytes_written) ||
|
||||
!encodePackedEnvironmentEntryBody(ostream, kv.first, kv.second))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
const auto *vec = static_cast<const std::vector<meshtastic_NodeEnvironmentEntry> *>(iter->pData);
|
||||
for (const auto &item : *vec) {
|
||||
@@ -465,7 +479,7 @@ bool meshtastic_NodeDatabase_callback(pb_istream_t *istream, pb_ostream_t *ostre
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
if (s_decodeEnvironmentTarget) {
|
||||
if (entry.has_environment_metrics && isUsableSatelliteKey(entry.num))
|
||||
(*s_decodeEnvironmentTarget)[entry.num] = entry.environment_metrics;
|
||||
(*s_decodeEnvironmentTarget)[entry.num].pack(entry.environment_metrics);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@@ -2076,10 +2090,41 @@ bool NodeDB::copyNodeEnvironment(NodeNum n, meshtastic_EnvironmentMetrics &out)
|
||||
return false;
|
||||
#else
|
||||
concurrency::LockGuard guard(&satelliteMutex);
|
||||
return copySatelliteEntry(nodeEnvironment, n, out);
|
||||
auto it = nodeEnvironment.find(n);
|
||||
return it != nodeEnvironment.end() && it->second.unpack(out);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NodeDB::hasNodeEnvironment(NodeNum n) const
|
||||
{
|
||||
#if MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
(void)n;
|
||||
return false;
|
||||
#else
|
||||
concurrency::LockGuard guard(&satelliteMutex);
|
||||
return nodeEnvironment.count(n) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PackedEnvironmentMetrics::pack(const meshtastic_EnvironmentMetrics &metrics)
|
||||
{
|
||||
uint8_t buf[meshtastic_EnvironmentMetrics_size];
|
||||
pb_ostream_t stream = pb_ostream_from_buffer(buf, sizeof(buf));
|
||||
if (!pb_encode(&stream, meshtastic_EnvironmentMetrics_fields, &metrics)) {
|
||||
bytes.clear();
|
||||
return false;
|
||||
}
|
||||
std::vector<uint8_t>(buf, buf + stream.bytes_written).swap(bytes); // exact capacity, no growth slack
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PackedEnvironmentMetrics::unpack(meshtastic_EnvironmentMetrics &out) const
|
||||
{
|
||||
out = meshtastic_EnvironmentMetrics_init_zero;
|
||||
pb_istream_t stream = pb_istream_from_buffer(bytes.data(), bytes.size());
|
||||
return pb_decode(&stream, meshtastic_EnvironmentMetrics_fields, &out);
|
||||
}
|
||||
|
||||
bool NodeDB::copyNodeStatus(NodeNum n, meshtastic_StatusMessage &out) const
|
||||
{
|
||||
#if MESHTASTIC_EXCLUDE_STATUSDB
|
||||
@@ -2244,7 +2289,9 @@ bool NodeDB::enforceSatelliteCaps()
|
||||
satBytes += nodeTelemetry.size() * (sizeof(decltype(nodeTelemetry)::value_type) + 44);
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
satBytes += nodeEnvironment.size() * (sizeof(decltype(nodeEnvironment)::value_type) + 44);
|
||||
// plus each entry's own encoded bytes, a separate allocation (~8 B allocator header)
|
||||
for (const auto &kv : nodeEnvironment)
|
||||
satBytes += sizeof(decltype(nodeEnvironment)::value_type) + 44 + kv.second.bytes.capacity() + 8;
|
||||
#endif
|
||||
#if !MESHTASTIC_EXCLUDE_STATUSDB
|
||||
satBytes += nodeStatus.size() * (sizeof(decltype(nodeStatus)::value_type) + 44);
|
||||
@@ -3838,7 +3885,7 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const meshtastic_Telemetry &t, RxS
|
||||
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTDB
|
||||
concurrency::LockGuard guard(&satelliteMutex);
|
||||
evictSatelliteOverCap(*this, nodeEnvironment, nodeId);
|
||||
nodeEnvironment[nodeId] = t.variant.environment_metrics;
|
||||
nodeEnvironment[nodeId].pack(t.variant.environment_metrics);
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
Reference in new issue
Block a user