Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/MESHCORE.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ Traceroute commands remain Meshtastic-only; MC feeders ignore `traceroute` WS me
| `advertisement` | Yes (`payload_type: advert`) | Identity only (`public_key`) |
| **`rx_log_data`** + `payload_typename: ADVERT` | Yes | **`adv_lat` / `adv_lon` / `adv_name`** (map coordinates in Meshflow UI) |
| `contact_message`, `channel_message` | Yes (text) | N/A |
| `rx_log_data` (TEXT_MSG, PATH, …) | No (`MeshCoreSkipUpload`) | N/A |
| `rx_log_data` + `TEXT_MSG` or `PATH` | Yes (`payload_type: raw`) | Path + `pkt_hash` for API twin-merge to channel messages |
| `rx_log_data` (REQ, CONTROL, …) | No (`MeshCoreSkipUpload`) | N/A |

Map coordinates in the Meshflow UI require **bot** [meshflow-bot#102](https://github.com/pskillen/meshflow-bot/issues/102) and **API** [meshflow-api#330](https://github.com/pskillen/meshflow-api/issues/330) / [#298](https://github.com/pskillen/meshflow-api/issues/298) deployed on feeders.

Expand Down
6 changes: 4 additions & 2 deletions src/meshcore/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

logger = logging.getLogger(__name__)

UPLOADABLE_PAYLOAD_TYPES = frozenset({"advert", "channel_text", "contact_text"})
UPLOADABLE_PAYLOAD_TYPES = frozenset({"advert", "channel_text", "contact_text", "raw"})


def _json_safe(value: Any) -> Any:
Expand Down Expand Up @@ -140,7 +140,9 @@ def _build_from_envelope(envelope: dict[str, Any]) -> dict[str, Any]:
"adv_lat": payload.get("adv_lat"),
"adv_lon": payload.get("adv_lon"),
}
raise MeshCoreSkipUpload(f"rx_log_data {typename} not uploaded in Phase 1")
if typename in ("TEXT_MSG", "PATH"):
return {**base, "payload_type": "raw"}
raise MeshCoreSkipUpload(f"rx_log_data {typename} not uploaded")

raise MeshCoreSkipUpload(f"event_type {event_type!r} not uploaded in Phase 1")

Expand Down
24 changes: 20 additions & 4 deletions test/meshcore/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import pytest

from src.data_classes import MeshNode
from src.meshcore.serializers import MeshCorePacketSerializer, MeshCoreSkipUpload
from src.meshcore.serializers import MeshCorePacketSerializer

DOCS = Path(__file__).resolve().parents[2] / "docs" / "meshcore_packets"

Expand Down Expand Up @@ -72,16 +72,32 @@ def test_serialise_contact_message() -> None:
assert out["from_pubkey_prefix"] == "e563a2e933ce"


def test_skip_rx_log_text() -> None:
def test_serialise_rx_log_text_msg() -> None:
dump = _load("rx_log_data/20260506_205845_837997.json")
raw = {
"meshcore": True,
"type": "rx_log_data",
"payload": dump["payload"],
"attributes": {},
}
with pytest.raises(MeshCoreSkipUpload):
MeshCorePacketSerializer().serialise_raw_packet(raw)
out = MeshCorePacketSerializer().serialise_raw_packet(raw)
assert out["payload_type"] == "raw"
assert out["event_type"] == "rx_log_data"
assert out["pkt_hash"] == dump["payload"]["pkt_hash"]


def test_serialise_rx_log_path() -> None:
dump = _load("rx_log_data/20260506_211515_351329.json")
raw = {
"meshcore": True,
"type": "rx_log_data",
"payload": dump["payload"],
"attributes": dump.get("attributes", {}),
}
out = MeshCorePacketSerializer().serialise_raw_packet(raw)
assert out["payload_type"] == "raw"
assert out["path_hashes"] == ["f3bcf1"]
assert out["path_hash_size"] == 3


def test_rx_log_data_serialises_bytes_in_raw_payload() -> None:
Expand Down