meshcore 2.3.0__tar.gz → 2.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {meshcore-2.3.0 → meshcore-2.3.2}/PKG-INFO +1 -1
- {meshcore-2.3.0 → meshcore-2.3.2}/pyproject.toml +1 -1
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/reader.py +2 -3
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/serial_cx.py +4 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/tcp_cx.py +4 -0
- meshcore-2.3.2/tests/unit/test_path_discovery_response.py +45 -0
- meshcore-2.3.2/tests/unit/test_serial_connection.py +31 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/.github/python-test.yml +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/.gitignore +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/LICENSE +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/README.md +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/.pubsub_example.py.swp +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_chat.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_pin_pairing_example.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_private_key_export.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_sign_example.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_stats.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_t1000_chan_msg.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_t1000_custom_vars.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_t1000_infos.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_t1000_msg.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_t1000_msg_retries.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/ble_t1000_set_cv.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/chan_recv_with_path.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/connection_events_example.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/mepo_mc_gps.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/pubsub_example.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/rf_packet_monitor.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_battery_monitor.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_channel_manager.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_chat.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_contacts.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_infos.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_meshcore_ollama.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_msg.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_pingbot.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_repeater_status.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_repeater_telemetry.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_rss_bot.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/serial_trace.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/tcp_chat.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/tcp_login_status.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/tcp_mchome_contacts.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/tcp_mchome_infos.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/tcp_mchome_msg.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/examples/tcp_mchome_readmsgs.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/pytest.ini +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/__init__.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/ble_cx.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/__init__.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/base.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/binary.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/contact.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/control_data.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/device.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/commands/messaging.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/connection_manager.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/events.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/lpp_json_encoder.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/meshcore.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/meshcore_parser.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/packets.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/src/meshcore/parsing.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/README.md +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/test_ble_connection.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/test_ble_pin_pairing.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/test_meshcore_ble_pin.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/unit/test_commands.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/unit/test_events.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/unit/test_private_key_export.py +0 -0
- {meshcore-2.3.0 → meshcore-2.3.2}/tests/unit/test_reader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcore
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.2
|
|
4
4
|
Summary: Base classes for communicating with meshcore companion radios
|
|
5
5
|
Project-URL: Homepage, https://github.com/fdlamotte/meshcore_py
|
|
6
6
|
Project-URL: Issues, https://github.com/fdlamotte/meshcore_py/issues
|
|
@@ -26,7 +26,6 @@ class MessageReader:
|
|
|
26
26
|
self.pending_binary_requests: Dict[str, Dict[str, Any]] = {} # tag -> {request_type, expires_at}
|
|
27
27
|
|
|
28
28
|
self.packet_parser = MeshcorePacketParser()
|
|
29
|
-
self.decrypt_channels = True
|
|
30
29
|
|
|
31
30
|
@property
|
|
32
31
|
def decrypt_channels(self):
|
|
@@ -828,13 +827,13 @@ class MessageReader:
|
|
|
828
827
|
res["pubkey_pre"] = dbuf.read(6).hex()
|
|
829
828
|
opl = dbuf.read(1)[0]
|
|
830
829
|
opl_hlen = ((opl & 0xc0) >> 6) + 1
|
|
831
|
-
opl = opl &
|
|
830
|
+
opl = opl & 0x3f
|
|
832
831
|
res["out_path_len"] = opl
|
|
833
832
|
res["out_path_hash_len"] = opl_hlen
|
|
834
833
|
res["out_path"] = dbuf.read(opl*opl_hlen).hex()
|
|
835
834
|
ipl = dbuf.read(1)[0]
|
|
836
835
|
ipl_hlen = ((ipl & 0xc0) >> 6) + 1
|
|
837
|
-
ipl = ipl &
|
|
836
|
+
ipl = ipl & 0x3f
|
|
838
837
|
res["in_path_len"] = ipl
|
|
839
838
|
res["in_path_hash_len"] = ipl_hlen
|
|
840
839
|
res["in_path"] = dbuf.read(ipl*ipl_hlen).hex()
|
|
@@ -79,6 +79,10 @@ class SerialConnection:
|
|
|
79
79
|
idx = data.find(b"\x3e")
|
|
80
80
|
if idx < 0: # no start of frame
|
|
81
81
|
return
|
|
82
|
+
# Discard any leading junk bytes before the actual frame marker.
|
|
83
|
+
# Some radios interleave console/debug text on the same UART, so
|
|
84
|
+
# valid companion frames may begin at an offset inside the chunk.
|
|
85
|
+
data = data[idx:]
|
|
82
86
|
self.header = data[0:1]
|
|
83
87
|
data = data[1:]
|
|
84
88
|
|
|
@@ -73,6 +73,10 @@ class TCPConnection:
|
|
|
73
73
|
idx = data.find(b"\x3e")
|
|
74
74
|
if idx < 0: # no start of frame
|
|
75
75
|
return
|
|
76
|
+
# Discard any leading junk bytes before the actual frame marker.
|
|
77
|
+
# Some radios interleave console/debug text on the same UART, so
|
|
78
|
+
# valid companion frames may begin at an offset inside the chunk.
|
|
79
|
+
data = data[idx:]
|
|
76
80
|
self.header = data[0:1]
|
|
77
81
|
data = data[1:]
|
|
78
82
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
|
|
3
|
+
from meshcore.events import EventType
|
|
4
|
+
from meshcore.reader import MessageReader
|
|
5
|
+
|
|
6
|
+
pytestmark = pytest.mark.asyncio
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class MockDispatcher:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self.dispatched_events = []
|
|
12
|
+
|
|
13
|
+
async def dispatch(self, event):
|
|
14
|
+
self.dispatched_events.append(event)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def test_path_discovery_response_decodes_3byte_paths():
|
|
18
|
+
dispatcher = MockDispatcher()
|
|
19
|
+
reader = MessageReader(dispatcher)
|
|
20
|
+
|
|
21
|
+
packet = bytearray.fromhex(
|
|
22
|
+
"8d" # PacketType.PATH_DISCOVERY_RESPONSE
|
|
23
|
+
"00" # Reserved byte
|
|
24
|
+
"112233445566" # 6-byte contact public-key prefix
|
|
25
|
+
"82" # Outbound path descriptor: mode=2 (3-byte hops), hop_count=2
|
|
26
|
+
"a1a2a3b1b2b3" # Outbound path bytes: 2 hops * 3 bytes each
|
|
27
|
+
"81" # Inbound path descriptor: mode=2 (3-byte hops), hop_count=1
|
|
28
|
+
"c1c2c3" # Inbound path bytes: 1 hop * 3 bytes
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
await reader.handle_rx(packet)
|
|
32
|
+
|
|
33
|
+
matching = [e for e in dispatcher.dispatched_events if e.type == EventType.PATH_RESPONSE]
|
|
34
|
+
assert len(matching) == 1
|
|
35
|
+
|
|
36
|
+
payload = matching[0].payload
|
|
37
|
+
assert payload["pubkey_pre"] == "112233445566"
|
|
38
|
+
|
|
39
|
+
assert payload["out_path_hash_len"] == 3
|
|
40
|
+
assert payload["out_path_len"] == 2
|
|
41
|
+
assert payload["out_path"] == "a1a2a3b1b2b3"
|
|
42
|
+
|
|
43
|
+
assert payload["in_path_hash_len"] == 3
|
|
44
|
+
assert payload["in_path_len"] == 1
|
|
45
|
+
assert payload["in_path"] == "c1c2c3"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from meshcore.serial_cx import SerialConnection
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RecordingReader:
|
|
9
|
+
def __init__(self):
|
|
10
|
+
self.frames = []
|
|
11
|
+
|
|
12
|
+
async def handle_rx(self, data):
|
|
13
|
+
self.frames.append(bytes(data))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.asyncio
|
|
17
|
+
async def test_handle_rx_discards_leading_junk_before_frame_start():
|
|
18
|
+
conn = SerialConnection("/dev/null", 115200)
|
|
19
|
+
reader = RecordingReader()
|
|
20
|
+
conn.set_reader(reader)
|
|
21
|
+
|
|
22
|
+
payload = b"\x00\x01\x02\x53"
|
|
23
|
+
frame = b"\x3e" + len(payload).to_bytes(2, "little") + payload
|
|
24
|
+
|
|
25
|
+
conn.handle_rx(b"junk bytes\r\n" + frame)
|
|
26
|
+
await asyncio.sleep(0)
|
|
27
|
+
|
|
28
|
+
assert reader.frames == [payload]
|
|
29
|
+
assert conn.header == b""
|
|
30
|
+
assert conn.inframe == b""
|
|
31
|
+
assert conn.frame_expected_size == 0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|