[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
# mc-webui

A lightweight web interface providing browser-based access to MeshCore mesh network.

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/MarekWo/mc-webui)

## Overview

**mc-webui** is a Flask-based web application providing browser-based access to MeshCore mesh network. It communicates directly with your LoRa device (via USB, BLE, or TCP) using the `meshcore` Python library, eliminating the need for SSH/terminal access. Tested on Heltec V3 and Heltec V4.

![Diagram](images/diagram.jpeg)

## Key Features

- **Mobile-first design** - Responsive UI optimized for small screens
- **Channel management** - Create, join, share (QR code), and switch between encrypted channels
- **Direct Messages (DM)** - Private messaging with searchable contact selector, delivery tracking, and configurable retry strategy
- **Smart notifications** - Unread message counters per channel with cross-device sync
- **Contact management** - Manual approval mode, filtering, protection, ignoring, blocking, batch operations, and cleanup tools
- **Global search** - Full-text search across all messages (channels and DMs) with FTS5 backend
- **Database** - Fast and reliable SQLite storage for messages, contacts, and configurations
- **Contact map** - View contacts and own device on OpenStreetMap (Leaflet) with last seen info
- **Message archives** - Automatic daily archiving with browse-by-date selector
- **Interactive Console** - Full MeshCore command suite via WebSocket — repeater, contact, device, and channel management
- **Device dashboard** - Device info and statistics with firmware details
- **Settings** - Configurable DM retry parameters, message retention, and quote length
- **System Log** - Real-time log viewer with streaming
- **Database backup** - Create, list, and download database backups from the UI
- **@Mentions autocomplete** - Type @ to see contact suggestions with fuzzy search
- **Echo tracking** - "Heard X repeats" with repeater IDs for sent messages, all route paths for incoming messages with deterministic payload matching (persisted across restarts)
- **MeshCore Analyzer** - View packet details on analyzer.letsmesh.net directly from channel messages
- **DM delivery tracking** - ACK-based delivery confirmation with SNR and route info
- **Multi-device support** - Database file named after device for easy multi-device setups
- **PWA support** - Browser notifications and installable app (experimental)
- **Full offline support** - Works without internet (local Bootstrap, icons, emoji picker)

For detailed feature documentation, see the [User Guide](docs/user-guide.md).

## Quick Start

### Prerequisites

**1. Meshcore Device (tested on Heltec V4)**
- Flash the device at [https://flasher.meshcore.co.uk/](https://flasher.meshcore.co.uk/). Choose the `Companion USB` role.
- Configure the device with the Meshcore mobile app (from Google Play Store / App Store): Name, Location (optional), Preset

**2. Linux Server**
- Git installed
- Docker and Docker Compose installed ([installation guide](docs/docker-install.md))

**Important Notes:**
- Powered by direct meshcore library integration (v2 architecture)
- No manual directory setup needed - all data stored in `./data/` inside the project directory
- Uses a single-container architecture with a fast SQLite database

---

### Installation

1. **Clone the repository**
    ```bash
    cd ~
    git clone https://github.com/MarekWo/mc-webui
    cd mc-webui
    ```

2. **Create configuration file**
    ```bash
    cp .env.example .env
    ```

    **In most cases, no changes are needed!** The defaults work automatically:
    - `MC_SERIAL_PORT=auto` - auto-detects your USB device
    - `MC_DEVICE_NAME=auto` - auto-detects device name from meshcli

    Optionally edit `.env` to set your timezone: `TZ=Europe/Warsaw`

    <details>
    <summary><b>Troubleshooting: Multiple USB devices or detection fails</b></summary>

    Check available serial devices:
    ```bash
    ls /dev/serial/by-id/
    ```

    If you see multiple devices, edit `.env` and set `MC_SERIAL_PORT` explicitly:
    ```bash
    MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_...
    ```

    </details>

3. **Verify Serial Device Permissions** (if needed)
    ```bash
    sudo usermod -aG dialout $USER
    # Log out and log back in for changes to take effect
    ```

4. **Build and run**
    ```bash
    python3 -m app.version freeze
    docker compose up -d --build
    ```

    This will:
    - Download base images (Python, Alpine Linux)
    - Install the `meshcore` Python library
    - Create `./data/` directory structure automatically
    - Start the mc-webui container

5. **Verify installation**
    ```bash
    docker compose ps
    ```

    The container should show `Up` status. Check logs if needed:
    ```bash
    docker compose logs -f
    ```

6. **Access the web interface**

   Open your browser and navigate to:
   ```
   http://<your-server-ip>:5000
   ```

   To find your server IP: `hostname -I | awk '{print $1}'`

7. **Initial Configuration (In Web UI)**
    - Main page loads with chat interface on "Public" channel
    - Wait for initial sync (1-2 minutes)
    - Optional: Enable manual contact approval in Contact Management

---

## Basic Usage

1. **View messages** - Main page shows chat history with auto-refresh every 10 seconds
2. **Send messages** - Type in the text field and press Enter (135 bytes for channels, 150 bytes for DM)
3. **Switch channels** - Use the dropdown in navbar
4. **Direct Messages** - Access via menu (☰) → "Direct Messages"
5. **Manage contacts** - Access via menu (☰) → "Contact Management"
6. **Console** - Access via menu (☰) → "Console" for MeshCore commands
7. **Search** - Access via menu (☰) → "Search" for full-text message search
8. **Settings** - Access via menu (☰) → "Settings" for DM retry and other configuration

For complete usage instructions, see the [User Guide](docs/user-guide.md).

---

## Updating

### Using the update script (recommended)

The easiest way to update mc-webui:

```bash
cd ~/mc-webui
./scripts/update.sh
```

The script automatically pulls changes, freezes the version, and rebuilds containers.

**Optional: Create a global alias for quick updates**

Add to your `~/.bashrc` or `~/.zshrc`:

```bash
alias mcupdate='~/mc-webui/scripts/update.sh'
```

Then reload your shell (`source ~/.bashrc`) and update anytime with:

```bash
mcupdate
```

### Manual update

If you prefer to run commands manually:

```bash
cd ~/mc-webui
git pull
python3 -m app.version freeze
docker compose up -d --build
```

The `python3 -m app.version freeze` command captures the current Git version (date + commit hash) for display in the app menu.

### Testing experimental features

The `dev` branch contains new features that are still being tested:

```bash
cd ~/mc-webui
git checkout dev
./scripts/update.sh
```

To return to the stable version:

```bash
cd ~/mc-webui
git checkout main
./scripts/update.sh
```

### Remote updates from web GUI (optional)

You can enable one-click updates directly from the mc-webui menu. This requires installing a small webhook service on the host machine.

**Install the updater service:**

```bash
cd ~/mc-webui
sudo ./scripts/updater/install.sh
```

The installer will:
- Create a systemd service `mc-webui-updater`
- Start a webhook server on port 5050 (localhost only)
- Enable automatic startup on boot

**Usage:**
1. Click the refresh button (↻) next to the version in the menu
2. If an update is available, an "Update" button appears
3. Click "Update" to trigger the update remotely
4. The app will automatically reload when the update completes

**Useful commands:**

```bash
# Check service status
systemctl status mc-webui-updater

# View logs
journalctl -u mc-webui-updater -f

# Uninstall
sudo ~/mc-webui/scripts/updater/install.sh --uninstall
```

**Security note:** The webhook listens only on localhost. The Docker container connects to it via the Docker bridge network.

---

## Gallery

<table>
  <tr>
    <td align="center"><a href="gallery/main_window.png"><img src="gallery/main_window.png" width="150"><br>Main Window</a></td>
    <td align="center"><a href="gallery/dm.png"><img src="gallery/dm.png" width="150"><br>Direct Messages</a></td>
    <td align="center"><a href="gallery/unread_msgs.png"><img src="gallery/unread_msgs.png" width="150"><br>Unread Messages</a></td>
    <td align="center"><a href="gallery/msg_archive.png"><img src="gallery/msg_archive.png" width="150"><br>Message Archive</a></td>
  </tr>
  <tr>
    <td align="center"><a href="gallery/menu_1.png"><img src="gallery/menu_1.png" width="150"><br>Menu (1)</a></td>
    <td align="center"><a href="gallery/menu_2.png"><img src="gallery/menu_2.png" width="150"><br>Menu (2)</a></td>
    <td align="center"><a href="gallery/device_info.png"><img src="gallery/device_info.png" width="150"><br>Device Info</a></td>
    <td align="center"><a href="gallery/update_check.png"><img src="gallery/update_check.png" width="150"><br>Update Check</a></td>
  </tr>
  <tr>
    <td align="center"><a href="gallery/update_available.png"><img src="gallery/update_available.png" width="150"><br>Update Available</a></td>
    <td align="center"><a href="gallery/remote_update.png"><img src="gallery/remote_update.png" width="150"><br>Remote Update</a></td>
    <td align="center"><a href="gallery/updated_successfully.png"><img src="gallery/updated_successfully.png" width="150"><br>Updated Successfully</a></td>
    <td align="center"><a href="gallery/meshcli_console.png"><img src="gallery/meshcli_console.png" width="150"><br>Meshcli Console</a></td>
  </tr>
  <tr>
    <td align="center"><a href="gallery/contact_management.png"><img src="gallery/contact_management.png" width="150"><br>Contact Management</a></td>
    <td align="center"><a href="gallery/existing_contacts.png"><img src="gallery/existing_contacts.png" width="150"><br>Existing Contacts</a></td>
    <td align="center"><a href="gallery/approve_contact.png"><img src="gallery/approve_contact.png" width="150"><br>Approve Contact</a></td>
    <td align="center"><a href="gallery/channel_management.png"><img src="gallery/channel_management.png" width="150"><br>Channel Management</a></td>
  </tr>
  <tr>
    <td align="center"><a href="gallery/global_search.png"><img src="gallery/global_search.png" width="150"><br>Global Search</a></td>
    <td align="center"><a href="gallery/message_filtering.png"><img src="gallery/message_filtering.png" width="150"><br>Message Filtering</a></td>
    <td align="center"><a href="gallery/DM_Settings.png"><img src="gallery/DM_Settings.png" width="150"><br>Settings</a></td>
    <td align="center"><a href="gallery/sytem_log.png"><img src="gallery/sytem_log.png" width="150"><br>System Log</a></td>
  </tr>
  <tr>
    <td align="center"><a href="gallery/map.png"><img src="gallery/map.png" width="150"><br>Map</a></td>
    <td align="center"><a href="gallery/map_individual.png"><img src="gallery/map_individual.png" width="150"><br>Map (Individual)</a></td>
    <td align="center"><a href="gallery/image_preview_1.png"><img src="gallery/image_preview_1.png" width="150"><br>Image Preview (1)</a></td>
    <td align="center"><a href="gallery/image_preview_2.png"><img src="gallery/image_preview_2.png" width="150"><br>Image Preview (2)</a></td>
  </tr>
</table>

---

## Documentation

| Document | Description |
|----------|-------------|
| [User Guide](docs/user-guide.md) | Complete feature documentation |
| [Architecture](docs/architecture.md) | Technical details, API reference |
| [Troubleshooting](docs/troubleshooting.md) | Common issues and solutions |
| [Docker Installation](docs/docker-install.md) | How to install Docker on Debian/Ubuntu |
| [Container Watchdog](docs/watchdog.md) | Auto-restart for unhealthy containers |

---

## Development Status

### Completed Features

- [x] Environment Setup & Docker Architecture (single-container, direct device access)
- [x] Backend Basics (REST API, SQLite database, meshcore library integration)
- [x] Frontend Chat View (Bootstrap UI, message display, quote/reply)
- [x] Message Sending (Send form, reply, quote with configurable length)
- [x] Intelligent Auto-refresh (10s checks, UI updates only when needed)
- [x] Contact Management (Approval, filtering, protection, ignore/block, batch operations, cleanup)
- [x] Channel Management (Create, join, share via QR, delete with auto-cleanup)
- [x] Public Channels (# prefix support, auto-key generation)
- [x] Message Archiving (Daily archiving with browse-by-date selector)
- [x] Smart Notifications (Unread counters per channel and total)
- [x] Direct Messages (DM) - Searchable contact selector, delivery tracking, configurable retry
- [x] Global Message Search - Full-text search across channels and DMs (FTS5)
- [x] Message Content Enhancements - Mention badges, clickable URLs, image previews
- [x] @Mentions Autocomplete - Type @ to get contact suggestions with fuzzy search
- [x] PWA Notifications (Experimental) - Browser notifications and app badge counters
- [x] Full Offline Support - Local Bootstrap libraries and Service Worker caching
- [x] Interactive Console - Full MeshCore command suite (repeater, contact, device, channel management)
- [x] Contact Map - View contacts and own device on OpenStreetMap (Leaflet)
- [x] Echo Tracking - "Heard X repeats" badge for sent channel messages
- [x] MeshCore Analyzer - Packet analysis links on channel messages (analyzer.letsmesh.net)
- [x] DM Delivery Tracking - ACK-based delivery checkmarks with SNR/route details
- [x] Device Dashboard - Device info and statistics with firmware details
- [x] Settings Modal - Configurable DM retry parameters and message retention
- [x] System Log - Real-time log viewer with streaming
- [x] Database Backup - Create, list, and download backups from the UI
- [x] Multi-device Support - Database file named after device name

### Next Steps

- [ ] Performance Optimization - Frontend and backend improvements
- [ ] Enhanced Testing - Unit and integration tests

---

## Security Notes

**Important**: This application is designed for **trusted local networks only** and has **no authentication**. Do not expose it to the internet without implementing proper security measures.

---

## Contributing

This is an open-source project. Contributions are welcome!

- All code, comments, and documentation must be in English
- Follow the existing code style
- Test your changes with real hardware if possible

---

## License

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)

---

## References

- [MeshCore Documentation](https://meshcore.org)
- [meshcore-cli GitHub](https://github.com/meshcore-dev/meshcore-cli)

---

## Buy me a coffee

If you appreciate what I am doing you can [buy me a coffee](https://buycoffee.to/marwoj) :)

<img src="images/QR_buycoffee.png" alt="Buy me a coffee" width="200px">

Thanks!

## Contact

<img src="images/MarWoj_card_QR.png" alt="meshcore://..." width="200px">
