Companion: say which profile raw and channel data arrived on

MeshCore Open TAK labels a MediaMesh photo or voice clip "Received via
MediaMesh", "via main mesh" or both. Wadamesh standalones tell the
app the profile in a frame byte stock firmware leaves reserved; a
Cascade companion left it unset, so the app showed nothing.

While radio2 is on (rx or rxtx):
- PUSH_CODE_RAW_DATA (0x84) byte 3: 0xA0 primary, 0xA1 radio2
  (stock 0xFF).
- RESP_CODE_CHANNEL_DATA_RECV (0x1B) byte 2: the same (stock 0).
With radio2 off, or for a packet from the UDP bridge, the stock values
stay, so existing clients see no change.

Test: test/test_companion_rx_via.py (in run-unit-tests); the two
harnesses that compile these handlers get a stub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011i5tJJtj95MB4oUgncCUe5
This commit is contained in:
Claude committed 2026-10-24 17:31:53 -07:00
1 parent 06edf9aa8a
commit 0e756bf24a
7 files changed
+108 -4

No files matched your search

+17 -2
View File
@@ -2358,7 +2358,7 @@ void MyMesh::onChannelDataRecv(const mesh::GroupChannel &channel, mesh::Packet *
int i = 0;
out_frame[i++] = RESP_CODE_CHANNEL_DATA_RECV;
out_frame[i++] = (int8_t)(pkt->getSNR() * 4);
out_frame[i++] = 0; // reserved1
out_frame[i++] = rxViaTag(pkt, 0); // reserved1: the profile it arrived on, while radio2 is on
out_frame[i++] = 0; // reserved2
const int selected_channel = findChannelIdxForPacket(channel, pkt);
@@ -2707,6 +2707,21 @@ void MyMesh::onControlDataRecv(mesh::Packet *packet) {
}
}
// Which profile a received packet arrived on, for the app, in a frame byte that
// stock firmware leaves reserved: 0xA0 the primary, 0xA1 radio2. MeshCore Open
// TAK shows it under a MediaMesh photo or voice clip ("Received via MediaMesh",
// "via main mesh", or both); Wadamesh standalones send the same tags. While
// radio2 is off everything is the primary, so the stock value (`none`) stays,
// as it does for a packet that came in over the UDP bridge.
uint8_t MyMesh::rxViaTag(const mesh::Packet *pkt, uint8_t none) const {
const mesh::RadioProfiles *profiles = _radio ? _radio->profiles() : nullptr;
if (!pkt || !profiles || !profiles->enabled()) return none;
#if defined(WITH_UDP_BRIDGE)
if (pkt->udp_bridge_ingress) return none;
#endif
return pkt->radio_origin == 1 ? 0xA1 : 0xA0;
}
void MyMesh::onRawDataRecv(mesh::Packet *packet) {
if (packet->payload_len + 4 > MAX_FRAME_SIZE) {
MESH_DEBUG_PRINTLN("onRawDataRecv(), payload_len too long: %d", packet->payload_len);
@@ -2716,7 +2731,7 @@ void MyMesh::onRawDataRecv(mesh::Packet *packet) {
out_frame[i++] = PUSH_CODE_RAW_DATA;
out_frame[i++] = (int8_t)(packet->getSNR() * 4);
out_frame[i++] = (int8_t)packet->getRSSI();
out_frame[i++] = 0xFF; // reserved (possibly path_len in future)
out_frame[i++] = rxViaTag(packet, 0xFF); // reserved: the profile it arrived on, while radio2 is on
memcpy(&out_frame[i], packet->payload, packet->payload_len);
i += packet->payload_len;
+3
View File
@@ -555,6 +555,9 @@ protected:
void onContactResponse(const ContactInfo &contact, const uint8_t *data, uint8_t len) override;
void onControlDataRecv(mesh::Packet *packet) override;
void onRawDataRecv(mesh::Packet *packet) override;
// The profile a received packet arrived on, for a frame's reserved byte
// (see rxViaTag in MyMesh.cpp).
uint8_t rxViaTag(const mesh::Packet *pkt, uint8_t none) const;
void onTraceRecv(mesh::Packet *packet, uint32_t tag, uint32_t auth_code, uint8_t flags,
const uint8_t *path_snrs, const uint8_t *path_hashes, uint8_t path_len) override;