Files
mc-webui/PRD.md
T
2025-12-21 12:31:28 +01:00

545 lines
21 KiB
Markdown

# PRD: mc-webui
## Product Requirements Document
**Version:** 1.0
**Date:** 2025-01-21
**Author:** Marek / Claude AI
---
## 1. Project Overview
### 1.1 Project Name
**mc-webui** - A simple web interface for meshcore-cli
### 1.2 Description
mc-webui is a lightweight web application that provides convenient access to the MeshCore network without requiring terminal/SSH access. The application serves as a wrapper around meshcore-cli, offering a user-friendly interface for viewing messages, sending communications, and basic contact management.
### 1.3 Problem Statement
Currently, using the MeshCore network via a Heltec V4 device connected to a Debian server requires:
- SSH connection to the virtual machine
- Knowledge of meshcore-cli commands
- Manual command entry in the terminal
mc-webui eliminates these barriers by providing browser-based access from any device on the local network.
### 1.4 Target Users
- Single user (single-user deployment)
- Access from multiple devices (computer, tablet, phone) via web browser
- Environment: trusted local network (no authentication requirement)
### 1.5 Existing Solutions
| Project | Assessment | Why It Doesn't Fit |
|---------|------------|-------------------|
| meshcore-hub | Feature-rich | Requires MQTT, too complex for single-user |
| MeshCore App (Flutter) | Official app | Requires BLE/WiFi, doesn't work with Serial over network |
| MeshTUI | Terminal UI | Still requires SSH |
mc-webui fills the niche of a **simple, lightweight web solution** for a single device.
---
## 2. Goals and Assumptions
### 2.1 Primary Goals (MVP)
1. **View messages** - display chat history from the Public channel
2. **Send messages** - publish to the Public channel
3. **Reply to users** - using `@[UserName] content` format
4. **Manage contacts** - clean up inactive contacts
### 2.2 Technical Assumptions
- **Backend:** Python 3.11+ with Flask
- **Frontend:** HTML5, Bootstrap 5, vanilla JavaScript
- **Deployment:** Docker / Docker Compose
- **MeshCore communication:** subprocess calls to `meshcli`
- **Data source:** `~/.config/meshcore/<device_name>.msgs` file
- **Refresh rate:** automatic every 60 seconds + manual button
### 2.3 Design Assumptions
- Minimalism - only essential features at launch
- Simple configuration - environment variables
- Responsive design - works on phone and desktop
- No authentication - trusted local network
---
## 3. Technical Architecture
### 3.1 Architecture Diagram
```
┌─────────────────────────────────────────────────────────────────┐
│ Host (Debian VM) │
│ ┌───────────────────────────────────────────────────────────┐ │
│ │ Docker Container │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Flask │◄────►│ meshcli │ │ │
│ │ │ Backend │ │ (subprocess) │ │
│ │ └──────┬──────┘ └──────┬──────┘ │ │
│ │ │ │ │ │
│ │ ▼ ▼ │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Bootstrap │ │ .msgs file │ │ │
│ │ │ Frontend │ │ (mounted) │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Heltec V4 │ │
│ │ (USB Serial) │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│ HTTP :5000
┌─────────────────┐
│ Browser │
│ (LAN/VPN) │
└─────────────────┘
```
### 3.2 Components
#### 3.2.1 Backend (Flask)
- **HTTP server** on port 5000
- **REST API** for frontend communication
- **meshcli wrapper** - command execution via subprocess
- **Parser for .msgs** - reading and parsing JSON Lines file
#### 3.2.2 Frontend (Bootstrap 5)
- **Chat view** - message list in messenger style
- **Send form** - text input field + button
- **Management panel** - contact cleanup
- **Auto-refresh** - JavaScript polling every 60s
#### 3.2.3 meshcore-cli Integration
Commands executed via subprocess:
```bash
# Fetch messages (trigger sync)
meshcli -s <SERIAL_PORT> recv
# Send to Public channel
meshcli -s <SERIAL_PORT> public "message content"
# Reply to user
meshcli -s <SERIAL_PORT> public "@[UserName] content"
# Clean up inactive contacts
meshcli -s <SERIAL_PORT> "apply_to u<48h,t=1 remove_contact"
# Get contact list
meshcli -s <SERIAL_PORT> contacts
```
### 3.3 Project File Structure
```
mc-webui/
├── docker/
│ ├── Dockerfile
│ └── docker-compose.yml
├── app/
│ ├── __init__.py
│ ├── main.py # Flask entry point
│ ├── config.py # Configuration
│ ├── meshcore/
│ │ ├── __init__.py
│ │ ├── cli.py # meshcli wrapper (subprocess)
│ │ └── parser.py # .msgs file parser
│ ├── routes/
│ │ ├── __init__.py
│ │ ├── api.py # API endpoints
│ │ └── views.py # HTML views
│ ├── static/
│ │ ├── css/
│ │ │ └── style.css # Custom styles
│ │ └── js/
│ │ └── app.js # Frontend logic
│ └── templates/
│ ├── base.html # Base template
│ ├── index.html # Main chat view
│ └── components/
│ ├── message.html # Message component
│ └── navbar.html # Navigation
├── requirements.txt
├── .env.example
├── README.md
└── PRD.md
```
---
## 4. Functional Requirements (MVP)
### 4.1 Module: Message Viewing
| ID | Requirement | Priority |
|----|-------------|----------|
| F1.1 | System displays message list from .msgs file | MUST |
| F1.2 | Messages are sorted chronologically (newest at bottom) | MUST |
| F1.3 | Each message contains: sender, content, timestamp | MUST |
| F1.4 | Own messages are visually distinguished (e.g., different side) | SHOULD |
| F1.5 | Auto-scroll to newest message | SHOULD |
| F1.6 | Display emoji (Unicode) | SHOULD |
**Message format in .msgs (JSON Lines):**
```json
{"type": "CHAN", "SNR": 10.5, "channel_idx": 0, "text": "UserName: content", "timestamp": 1766300846}
{"type": "SENT_CHAN", "channel_idx": 0, "text": "content", "name": "MarWoj", "timestamp": 1766309413}
```
### 4.2 Module: Message Sending
| ID | Requirement | Priority |
|----|-------------|----------|
| F2.1 | Form with text field and "Send" button | MUST |
| F2.2 | Send via Enter (Shift+Enter = new line) | SHOULD |
| F2.3 | Validation - non-empty field | MUST |
| F2.4 | Status feedback (success/error) | MUST |
| F2.5 | Clear field after sending | MUST |
### 4.3 Module: Replying to Users
| ID | Requirement | Priority |
|----|-------------|----------|
| F3.1 | "Reply" button on each message | MUST |
| F3.2 | Click inserts `@[UserName] ` into text field | MUST |
| F3.3 | Focus moves to text field | SHOULD |
### 4.4 Module: Contact Management
| ID | Requirement | Priority |
|----|-------------|----------|
| F4.1 | "Clean inactive contacts" button | MUST |
| F4.2 | Configurable inactivity hours (default 48h) | SHOULD |
| F4.3 | Confirmation before execution (modal) | MUST |
| F4.4 | Feedback on number of removed contacts | SHOULD |
### 4.5 Module: Data Refresh
| ID | Requirement | Priority |
|----|-------------|----------|
| F5.1 | Automatic refresh every 60 seconds | MUST |
| F5.2 | Manual refresh button | MUST |
| F5.3 | Last refresh indicator | SHOULD |
| F5.4 | Loading indicator during refresh | SHOULD |
---
## 5. Non-Functional Requirements
### 5.1 Performance
| ID | Requirement |
|----|-------------|
| NF1.1 | API response time < 2 seconds |
| NF1.2 | Handle .msgs file up to 10,000 messages |
| NF1.3 | Minimal resource usage (< 100MB RAM) |
### 5.2 Usability
| ID | Requirement |
|----|-------------|
| NF2.1 | Responsive design (mobile-first) |
| NF2.2 | Readable on screens 320px - 2560px |
| NF2.3 | Basic view works without JavaScript (graceful degradation) |
### 5.3 Reliability
| ID | Requirement |
|----|-------------|
| NF3.1 | Handle meshcli errors (timeout, device unavailable) |
| NF3.2 | Log errors to stdout/stderr (Docker logs) |
| NF3.3 | Automatic container restart on failure |
### 5.4 Security
| ID | Requirement |
|----|-------------|
| NF4.1 | No authentication (trusted network) - deliberate decision |
| NF4.2 | Input sanitization (injection protection) |
| NF4.3 | No sensitive data storage |
---
## 6. User Interface
### 6.1 Wireframe - Main View
```
┌────────────────────────────────────────────────────────────┐
│ mc-webui [↻ Refresh] [⚙️] │
├────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 12:30 MarioTJE🤖 │ │
│ │ Hey everyone [↩️] │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 12:35 BBKr │ │
│ │ @[Mruk-A] no it's ID conflict 01 [↩️] │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌────────────────────────────────────┐ │
│ │ 12:40 MarWoj (You) │ │
│ │ Good morning everyone │ │
│ └────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 12:45 Zen │ │
│ │ Good morning everyone, greetings [↩️] │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
├────────────────────────────────────────────────────────────┤
│ ┌──────────────────────────────────────────┐ ┌────────┐ │
│ │ Type a message... │ │ Send │ │
│ └──────────────────────────────────────────┘ └────────┘ │
├────────────────────────────────────────────────────────────┤
│ Last refresh: 12:46:30 Next in: 45s │
└────────────────────────────────────────────────────────────┘
```
### 6.2 Wireframe - Settings Panel (modal/dropdown)
```
┌─────────────────────────────────────┐
│ ⚙️ Settings ✕ │
├─────────────────────────────────────┤
│ │
│ Contact Management │
│ ───────────────────────────────── │
│ Remove contacts inactive for: │
│ [ 48 ] hours │
│ │
│ [🗑️ Clean Inactive Contacts] │
│ │
│ ───────────────────────────────── │
│ Device Information │
│ Name: MarWoj │
│ Port: /dev/serial/by-id/usb-... │
│ │
└─────────────────────────────────────┘
```
### 6.3 Colors and Style
- **Theme:** Light (dark mode possibility in future)
- **Primary colors:**
- Primary: #0d6efd (Bootstrap blue)
- Own messages: light blue background (#e7f1ff)
- Others' messages: white/gray background (#f8f9fa)
- **Fonts:** System fonts (Bootstrap defaults)
- **Icons:** Bootstrap Icons
---
## 7. Configuration
### 7.1 Environment Variables
| Variable | Description | Default Value |
|----------|-------------|---------------|
| `MC_SERIAL_PORT` | Path to serial device | `/dev/ttyUSB0` |
| `MC_DEVICE_NAME` | Device name (for .msgs file) | `MeshCore` |
| `MC_CONFIG_DIR` | meshcore configuration directory | `/root/.config/meshcore` |
| `MC_REFRESH_INTERVAL` | Refresh interval (seconds) | `60` |
| `MC_INACTIVE_HOURS` | Inactivity hours for cleanup | `48` |
| `FLASK_HOST` | Listen address | `0.0.0.0` |
| `FLASK_PORT` | Application port | `5000` |
| `FLASK_DEBUG` | Debug mode | `false` |
### 7.2 Example .env File
```env
# MeshCore device configuration
MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_wifi_lora_32_v4__16_MB_FLASH__2_MB_PSRAM__90706984A000-if00
MC_DEVICE_NAME=MarWoj
MC_CONFIG_DIR=/root/.config/meshcore
# Application settings
MC_REFRESH_INTERVAL=60
MC_INACTIVE_HOURS=48
# Flask
FLASK_HOST=0.0.0.0
FLASK_PORT=5000
FLASK_DEBUG=false
```
### 7.3 Docker Compose
```yaml
version: '3.8'
services:
mc-webui:
build: .
container_name: mc-webui
restart: unless-stopped
ports:
- "5000:5000"
devices:
- "${MC_SERIAL_PORT}:${MC_SERIAL_PORT}"
volumes:
- "${MC_CONFIG_DIR}:/root/.config/meshcore:rw"
environment:
- MC_SERIAL_PORT
- MC_DEVICE_NAME
- MC_REFRESH_INTERVAL
- MC_INACTIVE_HOURS
- FLASK_HOST
- FLASK_PORT
env_file:
- .env
```
---
## 8. Implementation Plan
### Phase 0: Environment Setup (0.5 day)
- [ ] Create GitHub repository
- [ ] Project directory structure
- [ ] Docker and docker-compose configuration
- [ ] Install meshcore-cli in container
- [ ] Verify device connection
### Phase 1: Backend - Basics (1 day)
- [ ] Flask application skeleton
- [ ] Configuration from environment variables
- [ ] meshcli wrapper (subprocess)
- [ ] .msgs file parser
- [ ] Basic API endpoints:
- `GET /api/messages` - message list
- `POST /api/messages` - send message
- `GET /api/status` - connection status
### Phase 2: Frontend - Chat View (1 day)
- [ ] Base template (Bootstrap 5)
- [ ] Message list view
- [ ] Distinguish own/others' messages
- [ ] Time formatting
- [ ] Emoji support
### Phase 3: Frontend - Message Sending (0.5 day)
- [ ] Send form
- [ ] Validation
- [ ] Feedback (toast notifications)
- [ ] Reply button (@[UserName])
### Phase 4: Auto-refresh (0.5 day)
- [ ] JavaScript polling
- [ ] Last refresh indicator
- [ ] Manual refresh button
- [ ] Smart scroll (don't jump if user is scrolling)
### Phase 5: Contact Management (0.5 day)
- [ ] Settings panel (modal)
- [ ] Contact cleanup function
- [ ] Action confirmation
- [ ] Result feedback
### Phase 6: Polish & Documentation (0.5 day)
- [ ] Manual testing
- [ ] Error handling and edge cases
- [ ] README with installation instructions
- [ ] Docker image optimization
**Total estimated time: ~4-5 working days**
---
## 9. Future Extensions (Backlog)
Features to consider in future versions:
| Priority | Feature | Description |
|----------|---------|-------------|
| HIGH | Dark mode | Dark theme interface |
| HIGH | Other channels | Send to channels other than Public |
| MEDIUM | Contact list | Browse and manage contacts |
| MEDIUM | Private messages | Send DMs to contacts |
| MEDIUM | Notifications | Audio/visual notifications for new messages |
| MEDIUM | Map | Display contact locations on map |
| LOW | Statistics | Message count, network activity |
| LOW | Telemetry | Display telemetry data |
| LOW | Authentication | Optional login (for internet access) |
| LOW | Multi-device | Support for multiple devices |
---
## 10. Risks and Limitations
### 10.1 Technical Risks
| Risk | Probability | Impact | Mitigation |
|------|-------------|--------|------------|
| meshcli delays | Medium | Medium | Timeout + async execution |
| Device connection loss | Low | High | Health check + restart |
| Large .msgs file | Low | Medium | Pagination, tail last N |
| Concurrent access conflicts | Low | Low | Command queuing |
### 10.2 Limitations
1. **Single-user** - no multi-user support
2. **No authentication** - requires trusted network
3. **meshcli dependency** - requires installed meshcore-cli
4. **Public channel only (MVP)** - other channels in future versions
5. **No persistence** - data only in .msgs file
### 10.3 Assumptions
1. Heltec V4 device is always connected and available
2. meshcore-cli is properly configured
3. .msgs file is regularly updated by meshcore-cli
4. Local network is trusted (no authentication needed)
---
## 11. Definitions and Abbreviations
| Term | Definition |
|------|------------|
| MeshCore | Mesh networking protocol for LoRa radios |
| meshcore-cli | Command-line interface for MeshCore |
| meshcli | Alias for meshcore-cli |
| Heltec V4 | Heltec WiFi LoRa 32 V4 - LoRa device |
| .msgs | JSON Lines file with message history |
| Public | Default public channel (channel 0) |
| SNR | Signal-to-Noise Ratio |
---
## 12. Changelog
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 1.0 | 2025-01-21 | Marek/Claude | Initial version |
---
## Appendices
### A. Example Message Format (.msgs)
```json
{"type": "CHAN", "SNR": 10.5, "channel_idx": 0, "path_len": 5, "txt_type": 0, "sender_timestamp": 1766300840, "text": "MarioTJE🤖: Hey everyone ", "name": "channel 0", "timestamp": 1766300846}
{"type": "SENT_CHAN", "channel_idx": 0, "text": "Good morning everyone", "txt_type": 0, "name": "MarWoj", "timestamp": 1766309432}
```
### B. meshcli Commands Used in Project
```bash
# Sync messages
meshcli -s <PORT> recv
# Send to Public
meshcli -s <PORT> public "message"
# Contact list
meshcli -s <PORT> contacts
# Clean inactive contacts (type client, >48h)
meshcli -s <PORT> "apply_to u<48h,t=1 remove_contact"
# Device information
meshcli -s <PORT> infos
```