- fs5 entrypoint with status, push, pull, app, shell, logs commands - lib/adb.sh: ADB wrapper functions with idempotency and --force guards - lib/output.sh: human + JSON output formatting via Python - 33 bats tests (6 status, 9 transfer, 7 app, 5 shell, 6 logs) — all passing - Zero shellcheck warnings - .env-based config (device serial, log path) - Spec-Driven Development artifacts in specs/001-android-fs5-management/ Device: exone GmbH FS5 (RD51QE202392, Android 9)
174 lines
6.5 KiB
Markdown
174 lines
6.5 KiB
Markdown
# Feature Specification: Android FS5 Device Management
|
|
|
|
**Feature Branch**: `001-android-fs5-management`
|
|
**Created**: 2026-03-02
|
|
**Status**: Draft
|
|
**Device**: exone GmbH FS5 (Serial: RD51QE202392, Android 9)
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
A CLI toolset for managing the exone GmbH FS5 Android device connected via USB/ADB.
|
|
Enables infrastructure operators to inspect device state, transfer files, manage apps,
|
|
and automate device operations from the command line on Manjaro Linux.
|
|
|
|
---
|
|
|
|
## User Scenarios & Testing
|
|
|
|
### User Story 1 — Device Status & Health Check (Priority: P1)
|
|
|
|
**Why this priority**: Operators need to verify device connectivity and health before
|
|
any operation. This is the entry point for all other workflows.
|
|
|
|
**Independent Test**: Run `./fs5 status` with device connected → shows device info.
|
|
Run with device disconnected → exits with code 2 and clear error message.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** the FS5 is connected via USB, **When** I run `./fs5 status`,
|
|
**Then** I see device model, Android version, serial, battery level, storage usage,
|
|
and ADB connection state.
|
|
|
|
2. **Given** no device is connected, **When** I run `./fs5 status`,
|
|
**Then** the tool exits with code 2 and prints "Device not found: RD51QE202392".
|
|
|
|
3. **Given** the FS5 is connected, **When** I run `./fs5 status --json`,
|
|
**Then** I receive a valid JSON object with all device properties.
|
|
|
|
---
|
|
|
|
### User Story 2 — File Transfer (Push/Pull) (Priority: P1)
|
|
|
|
**Why this priority**: File transfer is the most common daily operation for device management.
|
|
|
|
**Independent Test**: Push a test file to `/sdcard/test/` → verify it exists on device.
|
|
Pull it back → verify local copy matches original.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a local file exists, **When** I run `./fs5 push <local-path> <device-path>`,
|
|
**Then** the file is transferred to the device and a success message with file size is shown.
|
|
|
|
2. **Given** a file exists on the device, **When** I run `./fs5 pull <device-path> <local-path>`,
|
|
**Then** the file is downloaded locally and a success message with file size is shown.
|
|
|
|
3. **Given** the destination already contains the file, **When** I run `./fs5 push` without `--force`,
|
|
**Then** the operation is skipped with a warning "File exists, use --force to overwrite".
|
|
|
|
4. **Given** a directory path, **When** I run `./fs5 push <local-dir>/ <device-dir>/`,
|
|
**Then** all files in the directory are transferred recursively.
|
|
|
|
---
|
|
|
|
### User Story 3 — App Management (Priority: P2)
|
|
|
|
**Why this priority**: Installing, listing, and removing APKs is a frequent maintenance task.
|
|
|
|
**Independent Test**: List installed packages → verify output contains known system apps.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** an APK file, **When** I run `./fs5 app install <apk-path>`,
|
|
**Then** the app is installed and the package name is confirmed in output.
|
|
|
|
2. **Given** an installed package, **When** I run `./fs5 app uninstall <package-name>`,
|
|
**Then** the app is removed and exit code is 0.
|
|
|
|
3. **When** I run `./fs5 app list`,
|
|
**Then** I see all installed non-system packages with their version codes.
|
|
|
|
4. **When** I run `./fs5 app list --all`,
|
|
**Then** I see all packages including system apps.
|
|
|
|
---
|
|
|
|
### User Story 4 — Shell Command Execution (Priority: P2)
|
|
|
|
**Why this priority**: Enables ad-hoc device inspection and scripted automation.
|
|
|
|
**Independent Test**: Run `./fs5 shell "echo hello"` → output is "hello".
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **Given** a shell command, **When** I run `./fs5 shell "<command>"`,
|
|
**Then** the command executes on the device and stdout/stderr are forwarded.
|
|
|
|
2. **Given** a multi-line script, **When** I pipe it via `cat script.sh | ./fs5 shell`,
|
|
**Then** the script executes on the device.
|
|
|
|
---
|
|
|
|
### User Story 5 — Log Capture (Priority: P3)
|
|
|
|
**Why this priority**: Debugging device issues requires access to Android logcat.
|
|
|
|
**Independent Test**: Run `./fs5 logs --lines 10` → outputs exactly 10 log lines.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. **When** I run `./fs5 logs`,
|
|
**Then** logcat output streams to stdout until Ctrl+C.
|
|
|
|
2. **When** I run `./fs5 logs --lines <N>`,
|
|
**Then** the last N log lines are printed and the command exits.
|
|
|
|
3. **When** I run `./fs5 logs --filter <tag>`,
|
|
**Then** only log lines matching the tag are shown.
|
|
|
|
4. **When** I run `./fs5 logs --output <file>`,
|
|
**Then** logs are written to the specified file.
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
### Functional Requirements
|
|
|
|
- **FR-001**: System MUST detect and validate device connectivity before every operation.
|
|
- **FR-002**: System MUST support `--json` output on all commands.
|
|
- **FR-003**: System MUST use device serial `RD51QE202392` from configuration, not hardcoded.
|
|
- **FR-004**: System MUST log all write/mutating operations to a local log file with timestamps.
|
|
- **FR-005**: System MUST require `--force` flag for any destructive operation.
|
|
- **FR-006**: System MUST exit with code 2 when device is not found.
|
|
- **FR-007**: System MUST provide `--help` on all commands and subcommands.
|
|
- **FR-008**: System MUST be idempotent — re-running any command must not cause errors.
|
|
|
|
### Non-Functional Requirements
|
|
|
|
- **NFR-001**: Device status check MUST complete in < 3 seconds.
|
|
- **NFR-002**: File transfer MUST show progress for files > 1MB.
|
|
- **NFR-003**: All scripts MUST pass ShellCheck with zero warnings.
|
|
- **NFR-004**: Tool MUST work on Manjaro Linux with ADB 1.0.41+.
|
|
- **NFR-005**: No root access required on the device.
|
|
|
|
### Key Entities
|
|
|
|
- **Device**: The exone FS5 identified by serial number, with properties (model, OS, battery, storage).
|
|
- **Operation**: A command executed against the device (push, pull, install, shell, logs).
|
|
- **Config**: Project-level settings file (`.env`) storing device serial and default paths.
|
|
- **Log Entry**: Timestamped record of every mutating operation performed.
|
|
|
|
---
|
|
|
|
## Success Criteria
|
|
|
|
- **SC-001**: All 5 user stories have passing acceptance tests.
|
|
- **SC-002**: `./fs5 status` returns device info in < 3 seconds.
|
|
- **SC-003**: File push/pull operations are idempotent (safe to re-run).
|
|
- **SC-004**: Zero ShellCheck warnings across all scripts.
|
|
- **SC-005**: `--json` flag produces valid JSON on all commands.
|
|
- **SC-006**: Tool works correctly when device is disconnected (graceful error, exit code 2).
|
|
- **SC-007**: All destructive operations require explicit confirmation flag.
|
|
|
|
---
|
|
|
|
## Out of Scope
|
|
|
|
- GUI or web interface
|
|
- Wireless ADB (WiFi) setup automation
|
|
- Device rooting or system partition access
|
|
- Multi-device simultaneous management (future)
|
|
- Android backup/restore via `adb backup` (deprecated in Android 9+)
|