python-mobius 0.4.2__py3-none-any.whl → 0.4.3__py3-none-any.whl
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.
- mobius/__init__.py +1 -1
- mobius/relay.py +43 -5
- {python_mobius-0.4.2.dist-info → python_mobius-0.4.3.dist-info}/METADATA +1 -1
- {python_mobius-0.4.2.dist-info → python_mobius-0.4.3.dist-info}/RECORD +7 -7
- {python_mobius-0.4.2.dist-info → python_mobius-0.4.3.dist-info}/WHEEL +0 -0
- {python_mobius-0.4.2.dist-info → python_mobius-0.4.3.dist-info}/entry_points.txt +0 -0
- {python_mobius-0.4.2.dist-info → python_mobius-0.4.3.dist-info}/licenses/LICENSE +0 -0
mobius/__init__.py
CHANGED
mobius/relay.py
CHANGED
|
@@ -177,12 +177,52 @@ class RelayedMobiusDevice(MobiusDevice):
|
|
|
177
177
|
embedded in its payload (confirmed via reverse engineering:
|
|
178
178
|
coapRequest.getToken() == coapResponse.getToken()) -- never by
|
|
179
179
|
this outer frame's own message ID.
|
|
180
|
+
|
|
181
|
+
Retries exactly once on a timeout before actually raising --
|
|
182
|
+
confirmed via reverse engineering the app's own request-timeout
|
|
183
|
+
handling: it never treats a single timed-out relay round-trip as
|
|
184
|
+
a real failure, always transparently retrying (fresh send, same
|
|
185
|
+
request) once first, only surfacing a failure if the retry ALSO
|
|
186
|
+
times out. A relayed round-trip crosses BLE (to the gateway) and
|
|
187
|
+
then the Thread mesh itself (gateway to target and back) -- a
|
|
188
|
+
single dropped/delayed packet somewhere in that longer path is
|
|
189
|
+
evidently common enough that the app was built assuming it will
|
|
190
|
+
happen regularly, not as an edge case. Each attempt gets its own
|
|
191
|
+
fresh CoAP token (this library generates one per call already,
|
|
192
|
+
not tied to a single request object the way the app's own retry
|
|
193
|
+
reuses one) -- deliberately, so a late, delayed response to the
|
|
194
|
+
first, abandoned attempt can never be mismatched against the
|
|
195
|
+
retry's own, separate wait.
|
|
180
196
|
"""
|
|
181
197
|
if not self.gateway.is_connected:
|
|
182
198
|
raise IOError(
|
|
183
199
|
f"gateway device is not connected -- cannot relay to {self.peer.serial!r} through it"
|
|
184
200
|
)
|
|
185
201
|
|
|
202
|
+
last_timeout_token: Optional[int] = None
|
|
203
|
+
for attempt in (1, 2):
|
|
204
|
+
try:
|
|
205
|
+
return await self._relay_attempt(inner_request_frame, is_retry=(attempt == 2))
|
|
206
|
+
except asyncio.TimeoutError as err:
|
|
207
|
+
last_timeout_token = err.args[0] if err.args else None
|
|
208
|
+
if attempt == 1 and self.debug:
|
|
209
|
+
print(f" [relay debug] timed out waiting {self.timeout}s for "
|
|
210
|
+
f"{self.peer.serial!r} -- retrying once before giving up")
|
|
211
|
+
continue
|
|
212
|
+
|
|
213
|
+
raise IOError(
|
|
214
|
+
f"timed out waiting {self.timeout}s for a relayed response from target "
|
|
215
|
+
f"{self.peer.serial!r} (no CoAP indication received for token {last_timeout_token}, "
|
|
216
|
+
f"even after one retry)"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
async def _relay_attempt(self, inner_request_frame: bytes, is_retry: bool) -> ParsedFrame:
|
|
220
|
+
"""One full send-and-await cycle for _relay() -- split out so
|
|
221
|
+
_relay() itself can retry it once on a timeout without
|
|
222
|
+
duplicating this whole body. Raises asyncio.TimeoutError itself
|
|
223
|
+
(not wrapped in IOError) specifically so _relay() can catch just
|
|
224
|
+
that case to decide whether to retry; every other exception here
|
|
225
|
+
propagates as-is, unwrapped, straight out of _relay() too."""
|
|
186
226
|
token = next_coap_token()
|
|
187
227
|
# Confirmed always GET regardless of the inner operation -- see
|
|
188
228
|
# this module's docstring for why.
|
|
@@ -193,7 +233,8 @@ class RelayedMobiusDevice(MobiusDevice):
|
|
|
193
233
|
outer_frame = build_frame(OPGROUP_C2CI_REQUEST, COAP_OPCODE, coap_payload, outer_message_id)
|
|
194
234
|
|
|
195
235
|
if self.debug:
|
|
196
|
-
|
|
236
|
+
retry_note = " (retry)" if is_retry else ""
|
|
237
|
+
print(f" [relay debug] inner request frame{retry_note} ({len(inner_request_frame)}B): "
|
|
197
238
|
f"{inner_request_frame.hex()}")
|
|
198
239
|
print(f" [relay debug] target address: {self.peer.address.hex()} token: {token}")
|
|
199
240
|
print(f" [relay debug] outer request frame ({len(outer_frame)}B): {outer_frame.hex()}")
|
|
@@ -220,10 +261,7 @@ class RelayedMobiusDevice(MobiusDevice):
|
|
|
220
261
|
coap_response = await asyncio.wait_for(coap_future, timeout=self.timeout)
|
|
221
262
|
except asyncio.TimeoutError:
|
|
222
263
|
self.gateway._pending_coap_tokens.pop(token, None)
|
|
223
|
-
raise
|
|
224
|
-
f"timed out waiting {self.timeout}s for a relayed response from target "
|
|
225
|
-
f"{self.peer.serial!r} (no CoAP indication received for token {token})"
|
|
226
|
-
)
|
|
264
|
+
raise asyncio.TimeoutError(token) from None
|
|
227
265
|
finally:
|
|
228
266
|
if self.debug:
|
|
229
267
|
self.gateway.on_any_frame = previous_hook
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: python-mobius
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Reverse-engineered Python client for the Mobius BLE protocol (EcoTech Marine VorTech/Radion, AquaIllumination, Neptune Systems, NYOS)
|
|
5
5
|
Project-URL: Homepage, https://code.r3pek.org/r3pek/python-mobius
|
|
6
6
|
Project-URL: Documentation, https://code.r3pek.org/r3pek/python-mobius/src/branch/main/documentation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
mobius/__init__.py,sha256=
|
|
1
|
+
mobius/__init__.py,sha256=7MOkrkQcDD7HLG5C7hKh5BTzUp0PmB5ZfIa3esYn2Nc,5722
|
|
2
2
|
mobius/cli.py,sha256=8XH-pVTX4KObzd0IOGXicT7KrcNEjm5xYZS8JOWfHDA,30726
|
|
3
3
|
mobius/coap.py,sha256=eXf_-9heQD1UjLyqZU9KA-c0jB50NGzAd8D7d6kFMb0,10750
|
|
4
4
|
mobius/constants.py,sha256=z_KrFev5vGD9-9lKn4J0nGVtzTmelGQ13bYlVcCdjm0,25217
|
|
@@ -12,10 +12,10 @@ mobius/mesh_address.py,sha256=PKQ-mm7Z4bY11ZnVmeWZO9EmOiAHp8hNtXceMGMs2tk,5940
|
|
|
12
12
|
mobius/modifiers.py,sha256=zWJCsjaJ4TtwS1QgQoRFH-ve1mykuPWn5KX4YQpNqco,7215
|
|
13
13
|
mobius/power.py,sha256=5l9ehjNCDrSsJjQkaU4M6pYnSMqw2FVF8Ogg6KIE5vQ,3844
|
|
14
14
|
mobius/pump_status.py,sha256=RWTl8ZViCFDbiFU2mX-WAIH_cWhZOZ0M2B0oYXnPx3Y,1598
|
|
15
|
-
mobius/relay.py,sha256=
|
|
15
|
+
mobius/relay.py,sha256=bo2uUV6HhHD_-LuH4CkuPJtnKGQGM6crmB6kLAU8i4E,18857
|
|
16
16
|
mobius/schedule.py,sha256=d5iAHvKuFDwfbrSptPx6viiA_lj2qGfWhsZwM_Bpr1k,10974
|
|
17
|
-
python_mobius-0.4.
|
|
18
|
-
python_mobius-0.4.
|
|
19
|
-
python_mobius-0.4.
|
|
20
|
-
python_mobius-0.4.
|
|
21
|
-
python_mobius-0.4.
|
|
17
|
+
python_mobius-0.4.3.dist-info/METADATA,sha256=Iht60XXLlvjteO-wjyLMwUlzeKGlDKRL-mgIlv-sHx8,5952
|
|
18
|
+
python_mobius-0.4.3.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
19
|
+
python_mobius-0.4.3.dist-info/entry_points.txt,sha256=Q2hlcek-bWm70zvd12v32essflPgC2su-dKDHAqbPoE,48
|
|
20
|
+
python_mobius-0.4.3.dist-info/licenses/LICENSE,sha256=7a72Msu2Q-TnoiFxemxEGkwafJGObk1W3rw9hzmyM_Y,17984
|
|
21
|
+
python_mobius-0.4.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|