Compare commits
3 Commits
5f7acf38f0
...
713cd6e9a1
| Author | SHA1 | Date | |
|---|---|---|---|
| 713cd6e9a1 | |||
| 9e72c62481 | |||
|
|
eee9327e15 |
2
Pipfile
2
Pipfile
@@ -16,5 +16,5 @@ python_version = "3"
|
||||
[scripts]
|
||||
web = "python web.py"
|
||||
cli = "python cli.py"
|
||||
build = "pyinstaller --clean led-cli.spec"
|
||||
build = "pyinstaller --clean --onefile --name led-cli --paths lib cli.py"
|
||||
install = "pipenv install"
|
||||
|
||||
41
README.md
41
README.md
@@ -1,8 +1,39 @@
|
||||
# led-tool
|
||||
- `-s, --show`: Display current settings from device
|
||||
- `--no-download`: Don't download settings first (use empty settings)
|
||||
**Default behavior:** Downloads settings and prints them. If any edit flags are provided, settings are modified and uploaded automatically (unless `--no-upload` is specified).
|
||||
|
||||
## Device Connection
|
||||
CLI helpers for MicroPython LED devices: **`settings.json`** download/upload via **mpremote**, resets, follow/tail, recursive uploads, optional firmware flash, and **led-driver**-oriented flags (presets, transport, Wi-Fi fields).
|
||||
|
||||
The tools use an integrated mpremote transport to communicate with MicroPython devices. Make sure your device is connected and accessible via the specified serial port.## LicenseSee LICENSE file for details.
|
||||
Connection is always via **`-p` / `--port`** (default `/dev/ttyACM0`). There is **no** separate “server IP” flag; the Pi or PC address is configured on the device in **`settings.json`** when using Wi-Fi mode.
|
||||
|
||||
## Common flags
|
||||
|
||||
| Flag | Purpose |
|
||||
|------|--------|
|
||||
| `-p`, `--port` | Serial device (default `/dev/ttyACM0`) |
|
||||
| `-s`, `--show` | Print current settings from the device |
|
||||
| `-n`, `--name` | Device **name** |
|
||||
| `--id` | Numeric device id (ESP-NOW, 0–255) |
|
||||
| `--pin` | LED GPIO (`led_pin`) |
|
||||
| `-b`, `--brightness` | Brightness 0–255 |
|
||||
| `-l`, `--leds` | LED count (`num_leds`) |
|
||||
| `-d`, `--debug` | Debug 0 or 1 |
|
||||
| `-o`, `--order` | LED colour order (`rgb`, `grb`, …) |
|
||||
| `--preset` / `--pattern` | Create or replace a named preset in **led-driver** `presets.json` |
|
||||
| `--default` | Startup preset name |
|
||||
| `--transport` | `espnow` or `wifi` (`transport_type` on device) |
|
||||
| `--ssid`, `--wifi-password`, `--wifi-channel` | Wi-Fi / channel fields for the driver |
|
||||
| `-r`, `--reset` | Reset the device |
|
||||
| `-f`, `--follow` | Follow serial output (optional timeout seconds) |
|
||||
| `--pause` | Sleep N seconds (for chained actions) |
|
||||
| `-u`, `--upload` | Recursive upload: `-u SRC [DEST]` |
|
||||
| `--src`, `--lib` | Upload `src/` or a tree to `/lib` |
|
||||
| `-e` | Erase device code (keeps `settings.json`) |
|
||||
| `--rm` | Remove a path on the device |
|
||||
| `--flash` | Flash a firmware binary (uses **esptool** on the host) |
|
||||
|
||||
**Default behaviour:** the tool always downloads `settings.json`, prints the merged view, and uploads again **only** when you pass setting edits (`--name`, `--leds`, …), **`--preset`**, or the relevant upload/flash/erase actions in order.
|
||||
|
||||
Run **`python cli.py -h`** for the full epilog and argument list.
|
||||
|
||||
## License
|
||||
|
||||
See **LICENSE** in this directory.
|
||||
|
||||
37
cli.py
37
cli.py
@@ -154,7 +154,7 @@ _FLAGS_WITH_VALUE = frozenset({
|
||||
def _get_ordered_actions(argv: List[str]) -> List[tuple]:
|
||||
"""
|
||||
Scan argv and return list of (action_name, value) in order of appearance.
|
||||
Actions: flash, pause, reset, upload, erase_all, rm, follow.
|
||||
Actions: flash, pause, reset, upload, ls, erase_all, rm, follow.
|
||||
"""
|
||||
actions = []
|
||||
i = 1
|
||||
@@ -205,13 +205,18 @@ def _get_ordered_actions(argv: List[str]) -> List[tuple]:
|
||||
actions.append(('upload', [local_dir, ""]))
|
||||
continue
|
||||
if arg == '--lib':
|
||||
# Upload local DIR to /lib on device
|
||||
if i + 1 < len(argv):
|
||||
# Upload local DIR (default: ./lib) to /lib on device
|
||||
local_dir = "lib"
|
||||
if i + 1 < len(argv) and not argv[i + 1].startswith('-'):
|
||||
local_dir = argv[i + 1]
|
||||
actions.append(('upload', [local_dir, "lib"]))
|
||||
i += 2
|
||||
else:
|
||||
raise ValueError("--lib requires a directory argument")
|
||||
i += 1
|
||||
actions.append(('upload', [local_dir, "lib"]))
|
||||
continue
|
||||
if arg == '--ls':
|
||||
actions.append(('ls', None))
|
||||
i += 1
|
||||
continue
|
||||
if arg == '-e':
|
||||
actions.append(('erase_all', None))
|
||||
@@ -434,8 +439,16 @@ Examples:
|
||||
|
||||
parser.add_argument(
|
||||
"--lib",
|
||||
nargs="?",
|
||||
const="lib",
|
||||
metavar="DIR",
|
||||
help="Upload DIR recursively to /lib on device"
|
||||
help="Upload DIR recursively to /lib on device. If DIR is omitted, uses local ./lib."
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--ls",
|
||||
action="store_true",
|
||||
help="List files on the device root (:/)"
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
@@ -527,6 +540,18 @@ Examples:
|
||||
print(f"Error uploading directory: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
elif action_name == 'ls':
|
||||
try:
|
||||
print(f"Listing files on device {port}...", file=sys.stderr)
|
||||
conn = DeviceConnection(port)
|
||||
items = conn.list_files('')
|
||||
for name, is_dir, size in items:
|
||||
marker = "d" if is_dir else "-"
|
||||
print(f"{marker} {size:>8} {name}")
|
||||
except Exception as e:
|
||||
print(f"Error listing files: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
elif action_name == 'erase_all':
|
||||
try:
|
||||
print(f"Erasing all code on device {port}...", file=sys.stderr)
|
||||
|
||||
@@ -10,7 +10,7 @@ pipenv install "$@"
|
||||
if [ ! -f "dist/led-cli" ] || [ "cli.py" -nt "dist/led-cli" ] || [ "device.py" -nt "dist/led-cli" ]; then
|
||||
echo ""
|
||||
echo "Building binary..."
|
||||
pipenv run pyinstaller --clean led-cli.spec
|
||||
pipenv run pyinstaller --clean --onefile --name led-cli --paths lib cli.py
|
||||
fi
|
||||
|
||||
# Ensure ~/.local/bin exists
|
||||
|
||||
Reference in New Issue
Block a user