lr-shuttle 0.2.0__py3-none-any.whl → 0.2.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lr-shuttle
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: CLI and Python client for host-side of json based serial communication with embedded device bridge.
5
5
  Author-email: Jonas Estberger <jonas.estberger@lumenradio.com>
6
6
  License: MIT
@@ -1,18 +1,18 @@
1
- shuttle/cli.py,sha256=SxTNlqIfGviNQDloIUIVE2IffggkvVKne-GoN9VJJfA,69716
1
+ shuttle/cli.py,sha256=h8wElgPA-xN3MRUK3j_uBuWZs0hS_44bOc4WG_zYF_k,71365
2
2
  shuttle/constants.py,sha256=GUlAg3iEuPxLQ2mDCvlv5gVXHnlawl_YeLtaUSqsnPM,757
3
- shuttle/flash.py,sha256=a2KMECO4aVFuWtP0zrT7cELQgQuyDoSXNM1EBk1Wd-U,4416
3
+ shuttle/flash.py,sha256=9ph23MHL40SjKZoL38Sbd3JbykGb-ECxvzBzCIjAues,4492
4
4
  shuttle/prodtest.py,sha256=V0wkbicAb-kqMPKsvvi7lQgcPvto7M8RbACU9pf7y8I,3595
5
- shuttle/serial_client.py,sha256=B4ci-Ox-ig65H0xO32FgJHfTG0Ievg6VjGfQ_PSZjWE,17104
5
+ shuttle/serial_client.py,sha256=CnqWpC4CyxNXzsQQgRQsGwkDf19OoIEYvipu4kt2IQo,17392
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=xrS7cn4mllTXPtpBqpgjuA9863shD1TISgFkHfxMIGk,377792
10
+ shuttle/firmware/esp32c5/devboard.ino.bin,sha256=ehmd3EEcns5cAXrIqjQDxCQJr9JrKEdGqvScv0utF8Q,378880
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.0.dist-info/METADATA,sha256=DeZ2s75NvqbuHDa-4077ItWJuvLWEbSEvk5byWEa_mw,13037
15
- lr_shuttle-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- lr_shuttle-0.2.0.dist-info/entry_points.txt,sha256=obqdFPgvQLB1_EWcnD9ch8HjQRlNVT_pdB_EidDRDco,44
17
- lr_shuttle-0.2.0.dist-info/top_level.txt,sha256=PtNxNQQdya-Xs8DYublNTBTa8c1TrtfEpQ0lUd_OeZY,8
18
- lr_shuttle-0.2.0.dist-info/RECORD,,
14
+ lr_shuttle-0.2.1.dist-info/METADATA,sha256=NtysDMhV36TKVUVNlho_2zogxpYTDKl_sZjgdjCVRjQ,13037
15
+ lr_shuttle-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ lr_shuttle-0.2.1.dist-info/entry_points.txt,sha256=obqdFPgvQLB1_EWcnD9ch8HjQRlNVT_pdB_EidDRDco,44
17
+ lr_shuttle-0.2.1.dist-info/top_level.txt,sha256=PtNxNQQdya-Xs8DYublNTBTa8c1TrtfEpQ0lUd_OeZY,8
18
+ lr_shuttle-0.2.1.dist-info/RECORD,,
shuttle/cli.py CHANGED
@@ -1977,6 +1977,60 @@ def uart_rx_command(
1977
1977
  console.print("[yellow]No uart.rx events observed[/]")
1978
1978
 
1979
1979
 
1980
+ @app.command("power")
1981
+ def power_command(
1982
+ ctx: typer.Context,
1983
+ port: Optional[str] = typer.Option(
1984
+ None,
1985
+ "--port",
1986
+ envvar="SHUTTLE_PORT",
1987
+ help="Serial port (e.g., /dev/ttyUSB0)",
1988
+ ),
1989
+ baudrate: int = typer.Option(DEFAULT_BAUD, "--baud", help="Serial baud rate"),
1990
+ timeout: float = typer.Option(
1991
+ DEFAULT_TIMEOUT, "--timeout", help="Read timeout in seconds"
1992
+ ),
1993
+ enable: Optional[bool] = typer.Option(
1994
+ None,
1995
+ "--enable/--disable",
1996
+ help="Enable or disable the downstream power rail",
1997
+ ),
1998
+ ):
1999
+ """Query or toggle the downstream power rail."""
2000
+
2001
+ resources = _ctx_resources(ctx)
2002
+ resolved_port = _require_port(port)
2003
+ if enable is None:
2004
+ action = "Querying"
2005
+ label = "power.state"
2006
+ method_name = "power_state"
2007
+ elif enable:
2008
+ action = "Enabling"
2009
+ label = "power.enable"
2010
+ method_name = "power_enable"
2011
+ else:
2012
+ action = "Disabling"
2013
+ label = "power.disable"
2014
+ method_name = "power_disable"
2015
+
2016
+ with spinner(f"{action} power over {resolved_port}"):
2017
+ try:
2018
+ with NDJSONSerialClient(
2019
+ resolved_port,
2020
+ baudrate=baudrate,
2021
+ timeout=timeout,
2022
+ logger=resources.get("logger"),
2023
+ seq_tracker=resources.get("seq_tracker"),
2024
+ ) as client:
2025
+ method = getattr(client, method_name)
2026
+ response = method()
2027
+ except ShuttleSerialError as exc:
2028
+ console.print(f"[red]{exc}[/]")
2029
+ raise typer.Exit(1) from exc
2030
+
2031
+ _render_payload_response(label, response)
2032
+
2033
+
1980
2034
  @app.command("flash")
1981
2035
  def flash_command(
1982
2036
  ctx: typer.Context,
Binary file
shuttle/flash.py CHANGED
@@ -90,12 +90,16 @@ def flash_firmware(
90
90
  offset = segment.get("offset")
91
91
  file_name = segment.get("file")
92
92
  if not offset or not file_name:
93
- raise FirmwareFlashError("Manifest segment entries require 'offset' and 'file'")
93
+ raise FirmwareFlashError(
94
+ "Manifest segment entries require 'offset' and 'file'"
95
+ )
94
96
  traversable = resources.files(package) / file_name
95
97
  try:
96
98
  file_path = stack.enter_context(resources.as_file(traversable))
97
99
  except FileNotFoundError as exc:
98
- raise FirmwareFlashError(f"Missing firmware artifact: {file_name}") from exc
100
+ raise FirmwareFlashError(
101
+ f"Missing firmware artifact: {file_name}"
102
+ ) from exc
99
103
  resolved_segments.append((str(offset), Path(file_path)))
100
104
 
101
105
  if erase_first:
shuttle/serial_client.py CHANGED
@@ -324,6 +324,15 @@ class NDJSONSerialClient:
324
324
  def ping(self) -> Dict[str, Any]:
325
325
  return self._command("ping", {})
326
326
 
327
+ def power_state(self) -> Dict[str, Any]:
328
+ return self._command("power.state", {})
329
+
330
+ def power_enable(self) -> Dict[str, Any]:
331
+ return self._command("power.enable", {})
332
+
333
+ def power_disable(self) -> Dict[str, Any]:
334
+ return self._command("power.disable", {})
335
+
327
336
  def spi_cfg(self, spi: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
328
337
  payload: Dict[str, Any] = {}
329
338
  if spi: