meshcore 2.1.11__tar.gz → 2.1.13__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.
Potentially problematic release.
This version of meshcore might be problematic. Click here for more details.
- {meshcore-2.1.11 → meshcore-2.1.13}/PKG-INFO +1 -1
- {meshcore-2.1.11 → meshcore-2.1.13}/pyproject.toml +1 -1
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/commands/base.py +49 -38
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/commands/contact.py +25 -2
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/events.py +1 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/meshcore.py +0 -1
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/reader.py +1 -0
- meshcore-2.1.11/src/meshcore/commands/.binary.py.swp +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/.github/python-test.yml +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/.gitignore +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/LICENSE +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/README.md +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_chat.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_pin_pairing_example.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_private_key_export.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_t1000_chan_msg.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_t1000_custom_vars.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_t1000_infos.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_t1000_msg.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_t1000_msg_retries.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/ble_t1000_set_cv.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/connection_events_example.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/mepo_mc_gps.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/pubsub_example.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/rf_packet_monitor.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_battery_monitor.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_channel_manager.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_chat.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_contacts.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_infos.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_msg.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_repeater_status.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_repeater_telemetry.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/serial_trace.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/tcp_chat.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/tcp_login_status.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/tcp_mchome_contacts.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/tcp_mchome_infos.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/tcp_mchome_msg.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/examples/tcp_mchome_readmsgs.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/pytest.ini +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/__init__.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/ble_cx.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/commands/__init__.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/commands/binary.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/commands/device.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/commands/messaging.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/connection_manager.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/lpp_json_encoder.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/packets.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/parsing.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/serial_cx.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/src/meshcore/tcp_cx.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/README.md +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/test_ble_connection.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/test_ble_pin_pairing.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/test_meshcore_ble_pin.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/unit/test_commands.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/unit/test_events.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/unit/test_private_key_export.py +0 -0
- {meshcore-2.1.11 → meshcore-2.1.13}/tests/unit/test_reader.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcore
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.13
|
|
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
|
|
@@ -80,6 +80,53 @@ class CommandHandlerBase:
|
|
|
80
80
|
)-> None:
|
|
81
81
|
self._get_contact_by_prefix = func
|
|
82
82
|
|
|
83
|
+
async def wait_for_events(
|
|
84
|
+
self,
|
|
85
|
+
expected_events: Optional[Union[EventType, List[EventType]]] = None,
|
|
86
|
+
timeout: Optional[float] = None,
|
|
87
|
+
) -> Event:
|
|
88
|
+
try:
|
|
89
|
+
# Convert single event to list if needed
|
|
90
|
+
if not isinstance(expected_events, list):
|
|
91
|
+
expected_events = [expected_events]
|
|
92
|
+
|
|
93
|
+
logger.debug(f"Waiting for events {expected_events}, timeout={timeout}")
|
|
94
|
+
|
|
95
|
+
# Create futures for all expected events
|
|
96
|
+
futures = []
|
|
97
|
+
for event_type in expected_events:
|
|
98
|
+
future = asyncio.create_task(
|
|
99
|
+
self.dispatcher.wait_for_event(event_type, {}, timeout)
|
|
100
|
+
)
|
|
101
|
+
futures.append(future)
|
|
102
|
+
|
|
103
|
+
# Wait for the first event to complete or all to timeout
|
|
104
|
+
done, pending = await asyncio.wait(
|
|
105
|
+
futures, timeout=timeout, return_when=asyncio.FIRST_COMPLETED
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
# Cancel all pending futures
|
|
109
|
+
for future in pending:
|
|
110
|
+
future.cancel()
|
|
111
|
+
|
|
112
|
+
# Check if any future completed successfully
|
|
113
|
+
for future in done:
|
|
114
|
+
event = await future
|
|
115
|
+
if event:
|
|
116
|
+
return event
|
|
117
|
+
|
|
118
|
+
# Create an error event when no event is received
|
|
119
|
+
return Event(EventType.ERROR, {"reason": "no_event_received"})
|
|
120
|
+
except asyncio.TimeoutError:
|
|
121
|
+
logger.debug(f"Command timed out {data}")
|
|
122
|
+
return Event(EventType.ERROR, {"reason": "timeout"})
|
|
123
|
+
except Exception as e:
|
|
124
|
+
logger.debug(f"Command error: {e}")
|
|
125
|
+
return Event(EventType.ERROR, {"error": str(e)})
|
|
126
|
+
|
|
127
|
+
return Event(EventType.ERROR, {})
|
|
128
|
+
|
|
129
|
+
|
|
83
130
|
async def send(
|
|
84
131
|
self,
|
|
85
132
|
data: bytes,
|
|
@@ -110,45 +157,9 @@ class CommandHandlerBase:
|
|
|
110
157
|
await self._sender_func(data)
|
|
111
158
|
|
|
112
159
|
if expected_events:
|
|
113
|
-
try:
|
|
114
|
-
# Convert single event to list if needed
|
|
115
|
-
if not isinstance(expected_events, list):
|
|
116
|
-
expected_events = [expected_events]
|
|
117
|
-
|
|
118
|
-
logger.debug(f"Waiting for events {expected_events}, timeout={timeout}")
|
|
119
|
-
|
|
120
|
-
# Create futures for all expected events
|
|
121
|
-
futures = []
|
|
122
|
-
for event_type in expected_events:
|
|
123
|
-
future = asyncio.create_task(
|
|
124
|
-
self.dispatcher.wait_for_event(event_type, {}, timeout)
|
|
125
|
-
)
|
|
126
|
-
futures.append(future)
|
|
127
|
-
|
|
128
|
-
# Wait for the first event to complete or all to timeout
|
|
129
|
-
done, pending = await asyncio.wait(
|
|
130
|
-
futures, timeout=timeout, return_when=asyncio.FIRST_COMPLETED
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
# Cancel all pending futures
|
|
134
|
-
for future in pending:
|
|
135
|
-
future.cancel()
|
|
136
|
-
|
|
137
|
-
# Check if any future completed successfully
|
|
138
|
-
for future in done:
|
|
139
|
-
event = await future
|
|
140
|
-
if event:
|
|
141
|
-
return event
|
|
142
|
-
|
|
143
|
-
# Create an error event when no event is received
|
|
144
|
-
return Event(EventType.ERROR, {"reason": "no_event_received"})
|
|
145
|
-
except asyncio.TimeoutError:
|
|
146
|
-
logger.debug(f"Command timed out {data}")
|
|
147
|
-
return Event(EventType.ERROR, {"reason": "timeout"})
|
|
148
|
-
except Exception as e:
|
|
149
|
-
logger.debug(f"Command error: {e}")
|
|
150
|
-
return Event(EventType.ERROR, {"error": str(e)})
|
|
151
160
|
# For commands that don't expect events, return a success event
|
|
161
|
+
return await self.wait_for_events(expected_events, timeout)
|
|
162
|
+
|
|
152
163
|
return Event(EventType.OK, {})
|
|
153
164
|
|
|
154
165
|
# attached at base because its a common method
|
|
@@ -8,12 +8,35 @@ logger = logging.getLogger("meshcore")
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class ContactCommands(CommandHandlerBase):
|
|
11
|
-
async def get_contacts(self, lastmod=0) -> Event:
|
|
11
|
+
async def get_contacts(self, lastmod=0, anim=False) -> Event:
|
|
12
12
|
logger.debug("Getting contacts")
|
|
13
13
|
data = b"\x04"
|
|
14
14
|
if lastmod > 0:
|
|
15
15
|
data = data + lastmod.to_bytes(4, "little")
|
|
16
|
-
|
|
16
|
+
if anim:
|
|
17
|
+
print("Fetching contacts ", end="", flush=True)
|
|
18
|
+
# wait first event
|
|
19
|
+
res = await self.send(data)
|
|
20
|
+
while True:
|
|
21
|
+
# wait next event
|
|
22
|
+
res = await self.wait_for_events(
|
|
23
|
+
[EventType.NEXT_CONTACT, EventType.CONTACTS, EventType.ERROR],
|
|
24
|
+
timeout=5)
|
|
25
|
+
if res is None: # Timeout
|
|
26
|
+
if anim:
|
|
27
|
+
print(" Timeout")
|
|
28
|
+
return res
|
|
29
|
+
if res.type == EventType.ERROR:
|
|
30
|
+
if anim:
|
|
31
|
+
print(" Error")
|
|
32
|
+
return res
|
|
33
|
+
elif res.type == EventType.CONTACTS:
|
|
34
|
+
if anim:
|
|
35
|
+
print(" Done")
|
|
36
|
+
return res
|
|
37
|
+
elif res.type == EventType.NEXT_CONTACT:
|
|
38
|
+
if anim:
|
|
39
|
+
print(".", end="", flush=True)
|
|
17
40
|
|
|
18
41
|
async def reset_path(self, key: DestinationType) -> Event:
|
|
19
42
|
key_bytes = _validate_destination(key, prefix_length=32)
|
|
@@ -464,6 +464,5 @@ class MeshCore:
|
|
|
464
464
|
"""Ensure contacts are fetched"""
|
|
465
465
|
if not self._contacts or (follow and self._contacts_dirty):
|
|
466
466
|
await self.commands.get_contacts(lastmod=self._lastmod)
|
|
467
|
-
await self.wait_for_event(EventType.CONTACTS, timeout=30) # contact list can be huge
|
|
468
467
|
return True
|
|
469
468
|
return False
|
|
@@ -99,6 +99,7 @@ class MessageReader:
|
|
|
99
99
|
if packet_type_value == PacketType.PUSH_CODE_NEW_ADVERT.value:
|
|
100
100
|
await self.dispatcher.dispatch(Event(EventType.NEW_CONTACT, c))
|
|
101
101
|
else:
|
|
102
|
+
await self.dispatcher.dispatch(Event(EventType.NEXT_CONTACT, c))
|
|
102
103
|
self.contacts[c["public_key"]] = c
|
|
103
104
|
|
|
104
105
|
elif packet_type_value == PacketType.CONTACT_END.value:
|
|
Binary file
|
|
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
|