lr-shuttle 0.2.3__py3-none-any.whl → 0.2.4__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.
- {lr_shuttle-0.2.3.dist-info → lr_shuttle-0.2.4.dist-info}/METADATA +1 -1
- {lr_shuttle-0.2.3.dist-info → lr_shuttle-0.2.4.dist-info}/RECORD +9 -9
- shuttle/cli.py +20 -20
- shuttle/firmware/esp32c5/devboard.ino.bin +0 -0
- shuttle/prodtest.py +1 -3
- shuttle/serial_client.py +14 -1
- {lr_shuttle-0.2.3.dist-info → lr_shuttle-0.2.4.dist-info}/WHEEL +0 -0
- {lr_shuttle-0.2.3.dist-info → lr_shuttle-0.2.4.dist-info}/entry_points.txt +0 -0
- {lr_shuttle-0.2.3.dist-info → lr_shuttle-0.2.4.dist-info}/top_level.txt +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
shuttle/cli.py,sha256=
|
|
1
|
+
shuttle/cli.py,sha256=lou_JvWNoMXxoyXyz5MSIyAUZEUAe0CmXaBnl_gqLMY,93507
|
|
2
2
|
shuttle/constants.py,sha256=GUlAg3iEuPxLQ2mDCvlv5gVXHnlawl_YeLtaUSqsnPM,757
|
|
3
3
|
shuttle/flash.py,sha256=9ph23MHL40SjKZoL38Sbd3JbykGb-ECxvzBzCIjAues,4492
|
|
4
|
-
shuttle/prodtest.py,sha256=
|
|
5
|
-
shuttle/serial_client.py,sha256=
|
|
4
|
+
shuttle/prodtest.py,sha256=nI8k2OndhqsOv8BMtXwfcpGEdmHU7ywbIgMuW49EULU,8006
|
|
5
|
+
shuttle/serial_client.py,sha256=bUpTs6MmJkpYBgtNYZZ0EYaybkLlrM7MlhWxHLQPh3U,18185
|
|
6
6
|
shuttle/timo.py,sha256=1K18y0QtDF2lw2Abeok9PgrpPUiCEbQdGQXOQik75Hw,16481
|
|
7
7
|
shuttle/firmware/__init__.py,sha256=KRXyz3xJ2GIB473tCHAky3DdPIQb78gX64Qn-uu55To,120
|
|
8
8
|
shuttle/firmware/esp32c5/__init__.py,sha256=U2xXnb80Wv8EJaJ6Tv9iev1mVlpoaEeqsNmjmEtxdFQ,41
|
|
9
9
|
shuttle/firmware/esp32c5/boot_app0.bin,sha256=-UxdeGp6j6sGrF0Q4zvzdxGmaXY23AN1WeoZzEEKF_A,8192
|
|
10
|
-
shuttle/firmware/esp32c5/devboard.ino.bin,sha256=
|
|
10
|
+
shuttle/firmware/esp32c5/devboard.ino.bin,sha256=CxWJQYlbL7zu9nkUzBQ0PQQET4XHZKFoxMzm9tZonqk,1099040
|
|
11
11
|
shuttle/firmware/esp32c5/devboard.ino.bootloader.bin,sha256=LPU51SdUwebYemCZb5Pya-wGe7RC4UXrkRmBnsHePp0,20784
|
|
12
12
|
shuttle/firmware/esp32c5/devboard.ino.partitions.bin,sha256=FIuVnL_xw4qo4dXAup1hLFSZe5ReVqY_QSI-72UGU6E,3072
|
|
13
13
|
shuttle/firmware/esp32c5/manifest.json,sha256=CPOegfEK4PTtI6UPeohuUKkJNeg0t8aWntEczpoxYt4,480
|
|
14
|
-
lr_shuttle-0.2.
|
|
15
|
-
lr_shuttle-0.2.
|
|
16
|
-
lr_shuttle-0.2.
|
|
17
|
-
lr_shuttle-0.2.
|
|
18
|
-
lr_shuttle-0.2.
|
|
14
|
+
lr_shuttle-0.2.4.dist-info/METADATA,sha256=EEgzPGFjeZ3L04elKT8VcUkiRjm0CyUn9dAN5Cq4_IQ,13611
|
|
15
|
+
lr_shuttle-0.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
16
|
+
lr_shuttle-0.2.4.dist-info/entry_points.txt,sha256=obqdFPgvQLB1_EWcnD9ch8HjQRlNVT_pdB_EidDRDco,44
|
|
17
|
+
lr_shuttle-0.2.4.dist-info/top_level.txt,sha256=PtNxNQQdya-Xs8DYublNTBTa8c1TrtfEpQ0lUd_OeZY,8
|
|
18
|
+
lr_shuttle-0.2.4.dist-info/RECORD,,
|
shuttle/cli.py
CHANGED
|
@@ -107,7 +107,9 @@ for entry in PRODTEST_TX_POWER_LEVELS:
|
|
|
107
107
|
for alias in entry["aliases"]:
|
|
108
108
|
PRODTEST_TX_POWER_ALIASES[alias.lower()] = entry["value"]
|
|
109
109
|
PRODTEST_TX_POWER_ALIASES[str(entry["value"])] = entry["value"]
|
|
110
|
-
PRODTEST_TX_POWER_CANONICAL = [
|
|
110
|
+
PRODTEST_TX_POWER_CANONICAL = [
|
|
111
|
+
entry["aliases"][0] for entry in PRODTEST_TX_POWER_LEVELS
|
|
112
|
+
]
|
|
111
113
|
|
|
112
114
|
_HOST_PORT_PATTERN = re.compile(r"^[A-Za-z0-9_.-]+:\d+$")
|
|
113
115
|
_IPV6_HOST_PORT_PATTERN = re.compile(r"^\[[0-9A-Fa-f:]+\]:\d+$")
|
|
@@ -159,9 +161,7 @@ def _resolve_prodtest_power_choice(value: str) -> Tuple[int, Dict[str, str]]:
|
|
|
159
161
|
resolved = parsed
|
|
160
162
|
if resolved is None:
|
|
161
163
|
allowed = ", ".join(PRODTEST_TX_POWER_CANONICAL)
|
|
162
|
-
raise typer.BadParameter(
|
|
163
|
-
f"Power must be one of: {allowed} or an index 0-7"
|
|
164
|
-
)
|
|
164
|
+
raise typer.BadParameter(f"Power must be one of: {allowed} or an index 0-7")
|
|
165
165
|
return resolved, PRODTEST_TX_POWER_META[resolved]
|
|
166
166
|
|
|
167
167
|
|
|
@@ -259,9 +259,7 @@ def _resolve_uart_payload(
|
|
|
259
259
|
def _normalize_port(port: str) -> str:
|
|
260
260
|
trimmed = port.strip()
|
|
261
261
|
if not trimmed:
|
|
262
|
-
raise typer.BadParameter(
|
|
263
|
-
"Serial port is required (use --port or SHUTTLE_PORT)"
|
|
264
|
-
)
|
|
262
|
+
raise typer.BadParameter("Serial port is required (use --port or SHUTTLE_PORT)")
|
|
265
263
|
if "://" in trimmed:
|
|
266
264
|
return trimmed
|
|
267
265
|
if trimmed.startswith("/") or trimmed.startswith("\\"):
|
|
@@ -1568,7 +1566,9 @@ def prodtest_ping(
|
|
|
1568
1566
|
raise typer.Exit(1)
|
|
1569
1567
|
|
|
1570
1568
|
if len(responses) != len(sequence):
|
|
1571
|
-
console.print(
|
|
1569
|
+
console.print(
|
|
1570
|
+
"[red]Prodtest command halted before completing all SPI phases[/]"
|
|
1571
|
+
)
|
|
1572
1572
|
raise typer.Exit(1)
|
|
1573
1573
|
|
|
1574
1574
|
command_response, payload_response = responses
|
|
@@ -1583,9 +1583,7 @@ def prodtest_ping(
|
|
|
1583
1583
|
command_label="spi.xfer (prodtest payload)",
|
|
1584
1584
|
)
|
|
1585
1585
|
|
|
1586
|
-
rx_bytes = _decode_hex_response(
|
|
1587
|
-
payload_response, label="prodtest ping (payload)"
|
|
1588
|
-
)
|
|
1586
|
+
rx_bytes = _decode_hex_response(payload_response, label="prodtest ping (payload)")
|
|
1589
1587
|
if not rx_bytes or rx_bytes[0] != 0x2D: # ord('-')
|
|
1590
1588
|
console.print(
|
|
1591
1589
|
"[red]Ping failed: expected '-' (0x2D), got: "
|
|
@@ -1623,9 +1621,7 @@ def prodtest_antenna(
|
|
|
1623
1621
|
antenna_value = PRODTEST_ANTENNA_CHOICES[normalized]
|
|
1624
1622
|
except KeyError as exc:
|
|
1625
1623
|
allowed = ", ".join(sorted(PRODTEST_ANTENNA_CHOICES))
|
|
1626
|
-
raise typer.BadParameter(
|
|
1627
|
-
f"Antenna must be one of: {allowed}"
|
|
1628
|
-
) from exc
|
|
1624
|
+
raise typer.BadParameter(f"Antenna must be one of: {allowed}") from exc
|
|
1629
1625
|
|
|
1630
1626
|
sequence = [prodtest.select_antenna(antenna_value)]
|
|
1631
1627
|
responses = _execute_timo_sequence(
|
|
@@ -1767,7 +1763,9 @@ def prodtest_hw_device_id(
|
|
|
1767
1763
|
raise typer.Exit(1)
|
|
1768
1764
|
|
|
1769
1765
|
if len(responses) != len(sequence):
|
|
1770
|
-
console.print(
|
|
1766
|
+
console.print(
|
|
1767
|
+
"[red]Prodtest command halted before completing all SPI phases[/]"
|
|
1768
|
+
)
|
|
1771
1769
|
raise typer.Exit(1)
|
|
1772
1770
|
|
|
1773
1771
|
result_response = responses[-1]
|
|
@@ -1858,11 +1856,11 @@ def prodtest_serial_number(
|
|
|
1858
1856
|
result_response,
|
|
1859
1857
|
command_label="spi.xfer (prodtest payload)",
|
|
1860
1858
|
)
|
|
1861
|
-
rx_bytes = _decode_hex_response(
|
|
1862
|
-
result_response, label="prodtest serial-number"
|
|
1863
|
-
)
|
|
1859
|
+
rx_bytes = _decode_hex_response(result_response, label="prodtest serial-number")
|
|
1864
1860
|
if len(rx_bytes) < prodtest.SERIAL_NUMBER_LEN:
|
|
1865
|
-
console.print(
|
|
1861
|
+
console.print(
|
|
1862
|
+
"[red]Prodtest serial-number response shorter than expected[/]"
|
|
1863
|
+
)
|
|
1866
1864
|
raise typer.Exit(1)
|
|
1867
1865
|
serial_bytes = rx_bytes[-prodtest.SERIAL_NUMBER_LEN :]
|
|
1868
1866
|
console.print(f"Serial number: {_format_hex(serial_bytes.hex())}")
|
|
@@ -2476,7 +2474,9 @@ def wifi_cfg_command(
|
|
|
2476
2474
|
if parsed_gateway is not None:
|
|
2477
2475
|
network_payload["gateway"] = parsed_gateway
|
|
2478
2476
|
|
|
2479
|
-
dns_entries = [
|
|
2477
|
+
dns_entries = [
|
|
2478
|
+
entry for entry in (parsed_dns_primary, parsed_dns_secondary) if entry
|
|
2479
|
+
]
|
|
2480
2480
|
if dns_entries:
|
|
2481
2481
|
network_payload["dns"] = dns_entries
|
|
2482
2482
|
|
|
Binary file
|
shuttle/prodtest.py
CHANGED
|
@@ -62,9 +62,7 @@ def command(
|
|
|
62
62
|
) -> dict:
|
|
63
63
|
"""Build an NDJSON-ready spi.xfer payload for a prodtest command."""
|
|
64
64
|
|
|
65
|
-
return timo.command_payload(
|
|
66
|
-
_build_command_bytes(opcode, arguments), params=params
|
|
67
|
-
)
|
|
65
|
+
return timo.command_payload(_build_command_bytes(opcode, arguments), params=params)
|
|
68
66
|
|
|
69
67
|
|
|
70
68
|
def reset() -> dict:
|
shuttle/serial_client.py
CHANGED
|
@@ -229,10 +229,23 @@ class NDJSONSerialClient:
|
|
|
229
229
|
):
|
|
230
230
|
try:
|
|
231
231
|
self._serial = serial.serial_for_url(
|
|
232
|
-
url=port,
|
|
232
|
+
url=port,
|
|
233
|
+
baudrate=baudrate,
|
|
234
|
+
timeout=timeout,
|
|
235
|
+
do_not_open=True,
|
|
233
236
|
)
|
|
237
|
+
except SerialException as exc: # pragma: no cover - hardware specific
|
|
238
|
+
raise ShuttleSerialError(f"Unable to initialize {port}: {exc}") from exc
|
|
239
|
+
|
|
240
|
+
try:
|
|
241
|
+
if getattr(self._serial, "open", None) is not None:
|
|
242
|
+
if not getattr(self._serial, "is_open", False):
|
|
243
|
+
self._serial.open()
|
|
234
244
|
except SerialException as exc: # pragma: no cover - hardware specific
|
|
235
245
|
raise ShuttleSerialError(f"Unable to open {port}: {exc}") from exc
|
|
246
|
+
except AttributeError:
|
|
247
|
+
# Test stubs without an open() method are already "connected"
|
|
248
|
+
pass
|
|
236
249
|
self._serial.reset_input_buffer()
|
|
237
250
|
self._lock = threading.Lock()
|
|
238
251
|
self._pending: Dict[int, CommandFuture] = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|