mcuscope 0.1.0__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.
Files changed (53) hide show
  1. mcuscope-0.1.0/.gitignore +44 -0
  2. mcuscope-0.1.0/LICENSE +21 -0
  3. mcuscope-0.1.0/PKG-INFO +122 -0
  4. mcuscope-0.1.0/README.md +83 -0
  5. mcuscope-0.1.0/contrib/config.example.toml +48 -0
  6. mcuscope-0.1.0/contrib/mcuscoped.service +21 -0
  7. mcuscope-0.1.0/mcuscope/__init__.py +14 -0
  8. mcuscope-0.1.0/mcuscope/cli.py +1733 -0
  9. mcuscope-0.1.0/mcuscope/config.py +246 -0
  10. mcuscope-0.1.0/mcuscope/daemon.py +207 -0
  11. mcuscope-0.1.0/mcuscope/lockfile.py +159 -0
  12. mcuscope-0.1.0/mcuscope/protocol.py +651 -0
  13. mcuscope-0.1.0/mcuscope/serial_link.py +875 -0
  14. mcuscope-0.1.0/mcuscope/server.py +1626 -0
  15. mcuscope-0.1.0/mcuscope/sim.py +705 -0
  16. mcuscope-0.1.0/mcuscope/store.py +1606 -0
  17. mcuscope-0.1.0/mcuscope/webui/api.js +260 -0
  18. mcuscope-0.1.0/mcuscope/webui/app.js +130 -0
  19. mcuscope-0.1.0/mcuscope/webui/can.js +284 -0
  20. mcuscope-0.1.0/mcuscope/webui/cmdbar.js +190 -0
  21. mcuscope-0.1.0/mcuscope/webui/digital.js +510 -0
  22. mcuscope-0.1.0/mcuscope/webui/index.html +268 -0
  23. mcuscope-0.1.0/mcuscope/webui/plots.js +744 -0
  24. mcuscope-0.1.0/mcuscope/webui/settings.js +416 -0
  25. mcuscope-0.1.0/mcuscope/webui/state.js +271 -0
  26. mcuscope-0.1.0/mcuscope/webui/statusbar.js +315 -0
  27. mcuscope-0.1.0/mcuscope/webui/style.css +332 -0
  28. mcuscope-0.1.0/mcuscope/webui/terminal.js +449 -0
  29. mcuscope-0.1.0/mcuscope/webui/theme.js +25 -0
  30. mcuscope-0.1.0/mcuscope/webui/vendor/uPlot.iife.min.js +2 -0
  31. mcuscope-0.1.0/mcuscope/webui/vendor/uPlot.min.css +1 -0
  32. mcuscope-0.1.0/pyproject.toml +109 -0
  33. mcuscope-0.1.0/tests/__init__.py +0 -0
  34. mcuscope-0.1.0/tests/conftest.py +41 -0
  35. mcuscope-0.1.0/tests/support.py +128 -0
  36. mcuscope-0.1.0/tests/test_assert.py +320 -0
  37. mcuscope-0.1.0/tests/test_capture_lock.py +126 -0
  38. mcuscope-0.1.0/tests/test_cli.py +1098 -0
  39. mcuscope-0.1.0/tests/test_config_api.py +259 -0
  40. mcuscope-0.1.0/tests/test_e2e.py +353 -0
  41. mcuscope-0.1.0/tests/test_firmware_monitor.py +38 -0
  42. mcuscope-0.1.0/tests/test_hardening.py +776 -0
  43. mcuscope-0.1.0/tests/test_plot.py +281 -0
  44. mcuscope-0.1.0/tests/test_protocol.py +444 -0
  45. mcuscope-0.1.0/tests/test_reconnect.py +161 -0
  46. mcuscope-0.1.0/tests/test_regressions.py +381 -0
  47. mcuscope-0.1.0/tests/test_scaffold.py +22 -0
  48. mcuscope-0.1.0/tests/test_security.py +176 -0
  49. mcuscope-0.1.0/tests/test_sessions.py +507 -0
  50. mcuscope-0.1.0/tests/test_sim.py +198 -0
  51. mcuscope-0.1.0/tests/test_sim_pty.py +88 -0
  52. mcuscope-0.1.0/tests/test_sim_tcp.py +79 -0
  53. mcuscope-0.1.0/tests/test_webui.py +154 -0
@@ -0,0 +1,44 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ .mypy_cache/
13
+
14
+ # Packaging / lockfiles that should not be committed for a lib
15
+ *.egg
16
+
17
+ # C build artifacts
18
+ *.o
19
+ *.obj
20
+ *.a
21
+ *.elf
22
+ *.bin
23
+ *.hex
24
+ *.map
25
+
26
+ # Firmware host-test binary (no extension on POSIX, .exe on Windows)
27
+ firmware/tests/test_monitor
28
+ firmware/tests/test_monitor.exe
29
+ firmware/tests/test_monitor_asan
30
+ firmware/tests/test_monitor_asan.exe
31
+
32
+ # Capture databases
33
+ *.db
34
+ *.db-wal
35
+ *.db-shm
36
+
37
+ # Editor / OS cruft
38
+ .vscode/
39
+ .idea/
40
+ *.swp
41
+ .DS_Store
42
+
43
+ # superpowers brainstorm visual companion (local only)
44
+ .superpowers/
mcuscope-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Watman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcuscope
3
+ Version: 0.1.0
4
+ Summary: MCUscope: host daemon, CLI and web UI to debug, monitor and plot embedded targets over serial, for humans and AI agents.
5
+ Project-URL: Homepage, https://github.com/dwatman/mcuscope
6
+ Project-URL: Repository, https://github.com/dwatman/mcuscope
7
+ Project-URL: Issues, https://github.com/dwatman/mcuscope/issues
8
+ Author-email: Daniel Watman <dwatman@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: can,debug,embedded,i2c,mcu,microcontroller,oscilloscope,plotting,serial,spi,stm32,uart
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Visualization
20
+ Classifier: Topic :: Software Development :: Embedded Systems
21
+ Classifier: Topic :: System :: Hardware
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: fastapi<1.0,>=0.110
24
+ Requires-Dist: httpx<1.0,>=0.27
25
+ Requires-Dist: platformdirs>=4.0
26
+ Requires-Dist: pyserial>=3.5
27
+ Requires-Dist: regex>=2024.0
28
+ Requires-Dist: tomlkit<1.0,>=0.12
29
+ Requires-Dist: typer<1.0,>=0.12
30
+ Requires-Dist: uvicorn<1.0,>=0.29
31
+ Requires-Dist: websockets>=14.0
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
35
+ Requires-Dist: pytest-timeout>=2.3; extra == 'dev'
36
+ Requires-Dist: pytest>=8.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.5; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # MCUscope
41
+
42
+ **MCUscope** is a hardware debug bridge for embedded targets. It lets both humans and AI
43
+ agents (such as Claude Code) talk to an STM32 (or any) microcontroller over a serial link:
44
+ send CAN/I2C/SPI/GPIO/ADC commands, stream and query timestamped debug output, and plot
45
+ realtime data in the browser.
46
+
47
+ A single daemon (`mcuscoped`) owns the serial port, timestamps every line into SQLite, and
48
+ serves a local REST + WebSocket API and a web UI on `127.0.0.1:8765`. The `mcu` CLI is a
49
+ thin client over that API and is the primary interface for both the human and the agent.
50
+
51
+ This package (`mcuscope`) is the host side. The portable C firmware "monitor" module that
52
+ runs on the target, a hardware-free simulator, and the full specification live in the
53
+ [project repository](https://github.com/dwatman/mcuscope).
54
+
55
+ <!-- Absolute URL on purpose: PyPI does not resolve repo-relative image paths, and it only
56
+ renders once the repository is public. -->
57
+ ![MCUscope web UI](https://raw.githubusercontent.com/dwatman/mcuscope/main/docs/img/webui.png)
58
+
59
+ ## Install
60
+
61
+ Requires Python 3.11 or newer.
62
+
63
+ ```bash
64
+ uv tool install mcuscope # or: pipx install mcuscope
65
+ ```
66
+
67
+ This exposes three console scripts on your PATH: `mcuscoped` (the daemon), `mcu` (the
68
+ CLI), and `mcu-sim` (the hardware-free simulator).
69
+
70
+ To reach a real serial port, one OS-specific step:
71
+
72
+ - **Linux**: your user must be in the `dialout` group: `sudo usermod -aG dialout $USER`,
73
+ then log out and back in. Without it, opening `/dev/ttyACM0` fails with permission denied.
74
+ - **Windows 10/11**: most USB-serial adapters and ST-Link VCPs work with the in-box
75
+ driver; some need the vendor driver (CP210x, CH340, FTDI).
76
+
77
+ Neither is needed for the quickstart below, which runs with no hardware attached.
78
+
79
+ ## Quickstart
80
+
81
+ No hardware needed to try it:
82
+
83
+ ```bash
84
+ mcuscoped --sim --open # daemon + built-in simulator; opens the web UI
85
+ ```
86
+
87
+ The web UI at `http://127.0.0.1:8765/ui/` shows the live terminal, CAN table, and
88
+ realtime plots. The Plots panel also renders a Digital/Enum view (logic-analyser bit
89
+ traces and labelled enum/state bands) sharing the same time base and cursor as the
90
+ analog charts.
91
+
92
+ With real hardware, start the daemon first (it owns the port and captures everything),
93
+ then attach the port - from the UI's **+ Attach** dialog, or the CLI:
94
+
95
+ ```bash
96
+ mcuscoped # serves the API + web UI on :8765
97
+ # in another terminal (or use `mcu daemon start` to background the daemon):
98
+ mcu devices # find the port name
99
+ mcu attach /dev/ttyACM0 --baud 115200 --alias board # Linux
100
+ mcu attach COM7 --baud 115200 --alias board # Windows
101
+
102
+ mcu status # daemon + port health
103
+ mcu cmd ping # -> monitor 1 <project> (port-layer name, not the alias)
104
+ mcu cmd 'i2c scan' # -> 48 50
105
+ mcu tail -f # follow live capture
106
+ ```
107
+
108
+ Every command takes `--json` for a single machine-readable object and returns meaningful
109
+ exit codes (**0** success/match, **1** error or bad usage, **2** timeout, **3** daemon
110
+ unreachable). Run `mcu ai-guide` for a compact, agent-oriented cheat sheet.
111
+
112
+ The simulator also runs standalone (`mcu-sim`, prints e.g. `socket://127.0.0.1:9900`);
113
+ attach it like any device: `mcu attach socket://127.0.0.1:9900 --alias sim`.
114
+
115
+ ## Documentation
116
+
117
+ Full quickstart, configuration reference, protocol/API specification, and firmware
118
+ integration guide are in the [project repository](https://github.com/dwatman/mcuscope).
119
+
120
+ ## License
121
+
122
+ MIT
@@ -0,0 +1,83 @@
1
+ # MCUscope
2
+
3
+ **MCUscope** is a hardware debug bridge for embedded targets. It lets both humans and AI
4
+ agents (such as Claude Code) talk to an STM32 (or any) microcontroller over a serial link:
5
+ send CAN/I2C/SPI/GPIO/ADC commands, stream and query timestamped debug output, and plot
6
+ realtime data in the browser.
7
+
8
+ A single daemon (`mcuscoped`) owns the serial port, timestamps every line into SQLite, and
9
+ serves a local REST + WebSocket API and a web UI on `127.0.0.1:8765`. The `mcu` CLI is a
10
+ thin client over that API and is the primary interface for both the human and the agent.
11
+
12
+ This package (`mcuscope`) is the host side. The portable C firmware "monitor" module that
13
+ runs on the target, a hardware-free simulator, and the full specification live in the
14
+ [project repository](https://github.com/dwatman/mcuscope).
15
+
16
+ <!-- Absolute URL on purpose: PyPI does not resolve repo-relative image paths, and it only
17
+ renders once the repository is public. -->
18
+ ![MCUscope web UI](https://raw.githubusercontent.com/dwatman/mcuscope/main/docs/img/webui.png)
19
+
20
+ ## Install
21
+
22
+ Requires Python 3.11 or newer.
23
+
24
+ ```bash
25
+ uv tool install mcuscope # or: pipx install mcuscope
26
+ ```
27
+
28
+ This exposes three console scripts on your PATH: `mcuscoped` (the daemon), `mcu` (the
29
+ CLI), and `mcu-sim` (the hardware-free simulator).
30
+
31
+ To reach a real serial port, one OS-specific step:
32
+
33
+ - **Linux**: your user must be in the `dialout` group: `sudo usermod -aG dialout $USER`,
34
+ then log out and back in. Without it, opening `/dev/ttyACM0` fails with permission denied.
35
+ - **Windows 10/11**: most USB-serial adapters and ST-Link VCPs work with the in-box
36
+ driver; some need the vendor driver (CP210x, CH340, FTDI).
37
+
38
+ Neither is needed for the quickstart below, which runs with no hardware attached.
39
+
40
+ ## Quickstart
41
+
42
+ No hardware needed to try it:
43
+
44
+ ```bash
45
+ mcuscoped --sim --open # daemon + built-in simulator; opens the web UI
46
+ ```
47
+
48
+ The web UI at `http://127.0.0.1:8765/ui/` shows the live terminal, CAN table, and
49
+ realtime plots. The Plots panel also renders a Digital/Enum view (logic-analyser bit
50
+ traces and labelled enum/state bands) sharing the same time base and cursor as the
51
+ analog charts.
52
+
53
+ With real hardware, start the daemon first (it owns the port and captures everything),
54
+ then attach the port - from the UI's **+ Attach** dialog, or the CLI:
55
+
56
+ ```bash
57
+ mcuscoped # serves the API + web UI on :8765
58
+ # in another terminal (or use `mcu daemon start` to background the daemon):
59
+ mcu devices # find the port name
60
+ mcu attach /dev/ttyACM0 --baud 115200 --alias board # Linux
61
+ mcu attach COM7 --baud 115200 --alias board # Windows
62
+
63
+ mcu status # daemon + port health
64
+ mcu cmd ping # -> monitor 1 <project> (port-layer name, not the alias)
65
+ mcu cmd 'i2c scan' # -> 48 50
66
+ mcu tail -f # follow live capture
67
+ ```
68
+
69
+ Every command takes `--json` for a single machine-readable object and returns meaningful
70
+ exit codes (**0** success/match, **1** error or bad usage, **2** timeout, **3** daemon
71
+ unreachable). Run `mcu ai-guide` for a compact, agent-oriented cheat sheet.
72
+
73
+ The simulator also runs standalone (`mcu-sim`, prints e.g. `socket://127.0.0.1:9900`);
74
+ attach it like any device: `mcu attach socket://127.0.0.1:9900 --alias sim`.
75
+
76
+ ## Documentation
77
+
78
+ Full quickstart, configuration reference, protocol/API specification, and firmware
79
+ integration guide are in the [project repository](https://github.com/dwatman/mcuscope).
80
+
81
+ ## License
82
+
83
+ MIT
@@ -0,0 +1,48 @@
1
+ # Example mcuscope daemon configuration (SPEC 3.3).
2
+ # Copy to the platformdirs config location and edit:
3
+ # Linux: ~/.config/mcuscope/config.toml
4
+ # Windows: %LOCALAPPDATA%\mcuscope\mcuscope\config.toml
5
+ # All keys are optional; the file can also be edited from the web UI settings page.
6
+
7
+ [server]
8
+ host = "127.0.0.1" # bind "0.0.0.0" to reach the daemon across the LAN
9
+ port = 8765
10
+ # Note: the access token is NOT a config key. Set it at runtime instead
11
+ # (preferred: environment variable, so it is not visible in the process list):
12
+ # MCUSCOPED_TOKEN=long-random-string mcuscoped
13
+ # Generate one with: python -c "import secrets; print(secrets.token_urlsafe(24))"
14
+
15
+ [storage]
16
+ # Empty db_path uses the platformdirs data dir:
17
+ # Linux: ~/.local/share/mcuscope/capture.db
18
+ # Windows: %LOCALAPPDATA%\mcuscope\mcuscope\capture.db
19
+ db_path = ""
20
+ retention_days = 10
21
+
22
+ # The newest N sessions are never expired by age, however old they get. Age alone is a
23
+ # poor measure of what is worth keeping: a board captured over a quiet fortnight would
24
+ # otherwise lose its only recorded run to the calendar. 0 = pure age-based retention.
25
+ min_sessions = 5
26
+
27
+ # Open a session automatically for each daemon run, so the floor above has runs to protect
28
+ # even when nobody types `mcu session start`. Normal use names no sessions at all, so with
29
+ # this off the floor protects nothing and retention is age-based alone. An automatic run
30
+ # that captured no device traffic is dropped when it closes.
31
+ auto_session = true
32
+
33
+ # Optional hard bound on disk use. 0 (the default) means no cap: the capture is bounded
34
+ # by retention_days alone and nothing is ever dropped for size. When set, the daemon
35
+ # trims the OLDEST lines once the capture exceeds it, so set it generously - the web UI
36
+ # status bar shows the current capture size to size it against.
37
+ # max_db_bytes = 2147483648 # 2 GiB
38
+
39
+ # One [[ports]] block per serial port. Attach the simulator with a socket URL, or a
40
+ # real board by device path / COM name, or by USB serial number (stable across replug
41
+ # on both Linux and Windows).
42
+
43
+ [[ports]]
44
+ alias = "board"
45
+ device = "socket://127.0.0.1:9900" # sim; or /dev/ttyACM0, COM7, /dev/serial/by-id/...
46
+ # serial_number = "066BFF3..." # alternative to device: resolve via list_ports
47
+ baud = 115200
48
+ autoconnect = true
@@ -0,0 +1,21 @@
1
+ # systemd user unit for mcuscoped (Linux convenience only; SPEC 3.1).
2
+ # Install:
3
+ # mkdir -p ~/.config/systemd/user
4
+ # cp mcuscoped.service ~/.config/systemd/user/
5
+ # systemctl --user daemon-reload
6
+ # systemctl --user start mcuscoped
7
+ # Enabling it at login (OS-level autostart) is intentionally left to the user;
8
+ # automated enable/disable is a P2 item.
9
+
10
+ [Unit]
11
+ Description=mcuscope hardware debug bridge daemon
12
+ After=network.target
13
+
14
+ [Service]
15
+ Type=simple
16
+ ExecStart=%h/.local/bin/mcuscoped
17
+ Restart=on-failure
18
+ RestartSec=2
19
+
20
+ [Install]
21
+ WantedBy=default.target
@@ -0,0 +1,14 @@
1
+ """mcuscope: host daemon and CLI for MCUscope, a hardware debug and plotting bridge.
2
+
3
+ See docs/SPEC.md for the authoritative protocol and API contract. The package is
4
+ split into small modules:
5
+
6
+ - protocol: pure encode/decode of the UART line protocol (no I/O).
7
+ - store: SQLite capture storage.
8
+ - serial_link: per-port serial handling, seq machinery, reconnect.
9
+ - server: FastAPI REST + WebSocket app.
10
+ - daemon: mcuscoped entry point (config load, wiring, lifecycle).
11
+ - cli: the mcu command-line client.
12
+ """
13
+
14
+ __version__ = "0.1.0"