The session flood scope is framed by MeshTerm, so an older meshcore 2.3 can send scoped
reset_flood_scope and force_unscoped arrived late in meshcore 2.3.x. The uConsole's 2.3.7 satisfies meshcore>=2.3 without them, so every scoped channel send would have crashed on restoring the scope. set_flood_scope now sends the firmware's command 54 itself ([54][0][key], [54][0], [54][1]), as the default scope's command 63 already was. Every other library call MeshTerm makes exists in 2.3.7. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
b0d89a5ece
commit
01a8f711d6
2 files changed
+28
-8
No files matched your search
@@ -323,6 +323,11 @@ _CMD_SET_AUTOADD_CONFIG = 58
|
||||
#: :meth:`MeshCoreDevice.set_default_flood_scope` itself rather than the library.
|
||||
_CMD_SET_DEFAULT_FLOOD_SCOPE = 63
|
||||
|
||||
#: Companion command that sets (or clears, or forces off) the session flood scope
|
||||
#: (firmware 1.10+; the force-unscoped mode 1.16+), framed by
|
||||
#: :meth:`MeshCoreDevice.set_flood_scope` itself rather than the library.
|
||||
_CMD_SET_FLOOD_SCOPE_KEY = 54
|
||||
|
||||
#: ``RESP_CODE_AUTOADD_CONFIG`` — the reply to a read of the auto-add configuration. Its
|
||||
#: second payload byte is the hop limit, which the library's parser drops (it keeps only the
|
||||
#: bitmask), so :meth:`MeshCoreDevice.get_autoadd_config` recognises the raw frame by this.
|
||||
@@ -3240,16 +3245,23 @@ class MeshCoreDevice(Device):
|
||||
self._ok(await mc.commands.send(frame, [EventType.OK, EventType.ERROR]))
|
||||
|
||||
async def set_flood_scope(self, region: str | None) -> None: # noqa: D102
|
||||
commands = self._require().commands
|
||||
from meshcore import EventType
|
||||
|
||||
# Framed here, like the default scope, rather than through the library's helpers:
|
||||
# ``reset_flood_scope`` and ``force_unscoped`` arrived late in meshcore 2.3.x, and
|
||||
# an install that satisfies ``meshcore>=2.3`` without them (the uConsole's 2.3.7)
|
||||
# crashed every scoped channel send on the restore. The frame is the firmware's
|
||||
# own ``CMD_SET_FLOOD_SCOPE_KEY``: ``[54][0][key16]`` sets the session scope,
|
||||
# ``[54][0]`` alone clears it back to the default, ``[54][1]`` forces unscoped.
|
||||
bare = normalize_region(region) if region else ""
|
||||
if not bare:
|
||||
self._ok(await commands.reset_flood_scope())
|
||||
frame = bytes([_CMD_SET_FLOOD_SCOPE_KEY, 0])
|
||||
elif bare == REGION_WILDCARD:
|
||||
self._ok(await commands.force_unscoped())
|
||||
frame = bytes([_CMD_SET_FLOOD_SCOPE_KEY, 1])
|
||||
else:
|
||||
# The key goes over as bytes, which the library sends as-is — its string path
|
||||
# would derive the same key, but through its own ``#`` handling.
|
||||
self._ok(await commands.set_flood_scope(region_key(validate_region(bare))))
|
||||
frame = bytes([_CMD_SET_FLOOD_SCOPE_KEY, 0]) + region_key(validate_region(bare))
|
||||
mc = self._require()
|
||||
self._ok(await mc.commands.send(frame, [EventType.OK, EventType.ERROR]))
|
||||
|
||||
async def set_manual_add_contacts(self, enabled: bool) -> None: # noqa: D102
|
||||
self._ok(await self._require().commands.set_manual_add_contacts(enabled))
|
||||
|
||||
+10
-2
@@ -285,13 +285,21 @@ def test_default_scope_frame_is_bare_and_byte_padded() -> None:
|
||||
|
||||
|
||||
def test_session_scope_sends_the_key_the_override_or_the_reset() -> None:
|
||||
"""A name sends its key; ``*`` forces unscoped; ``None`` falls back to the default."""
|
||||
"""A name sends its key; ``*`` forces unscoped; ``None`` falls back to the default.
|
||||
|
||||
Framed by MeshTerm as the firmware's command 54, never through the library's
|
||||
``reset_flood_scope``/``force_unscoped``, which an older meshcore 2.3 lacks.
|
||||
"""
|
||||
commands = _Commands()
|
||||
device = _device(commands)
|
||||
asyncio.run(device.set_flood_scope("#harbour"))
|
||||
asyncio.run(device.set_flood_scope("*"))
|
||||
asyncio.run(device.set_flood_scope(None))
|
||||
assert commands.calls == [("scope", region_key("harbour")), ("unscoped",), ("reset",)]
|
||||
assert commands.calls == [
|
||||
("send", bytes([54, 0]) + region_key("harbour")),
|
||||
("send", bytes([54, 1])),
|
||||
("send", bytes([54, 0])),
|
||||
]
|
||||
|
||||
|
||||
def test_mock_device_mirrors_scope_and_answers_regions_from_repeaters() -> None:
|
||||
|
||||
Reference in new issue
Block a user