diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..7e5a91dd --- /dev/null +++ b/.dockerignore @@ -0,0 +1,63 @@ +# Git +.git +.gitignore + +# Python cache +__pycache__ +*.py[cod] +*$py.class +.cache +.cache.* +.cache.sqlite + +# Virtual environments +.venv +venv +env +ENV + +# IDE files +.vscode +.idea +*.swp +*.swo + +# OS files +.DS_Store +Thumbs.db + +# Logs and databases (will be mounted as volumes) +*.log +*.db +*.db-wal +*.db-shm + +# Config (will be mounted as volume) +config.ini + +# Documentation (not needed in container) +docs/ +*.md +!README.md + +# Service installation scripts (not needed in container) +*.service +*.plist +install-service.sh +uninstall-service.sh +restart_viewer.sh + +# Test files +test_*.py +*_test.py +tests/ +test_scripts/ + +# Development artifacts +docs/local/ +bot_start_time.txt +mctomqtt.py +bot_cli.py + +# Docker files (no need to copy into context) +docker-compose*.yml diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 00000000..ac77d162 --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,494 @@ +# MeshCore Bot Docker Deployment Guide + +This guide covers running MeshCore Bot in Docker containers with support for Serial, TCP, and BLE connections. + +## Quick Start + +### Prerequisites + +- Docker Engine 20.10+ +- Docker Compose 2.0+ +- For Serial: USB device access permissions +- For BLE: Bluetooth hardware and BlueZ on host + +### 1. Build the Image + +```bash +docker-compose build +``` + +### 2. Configure the Bot + +```bash +# Copy the example config +cp config.ini.example config.ini + +# Edit with your settings +nano config.ini +``` + +**Important settings to configure:** +- `[Connection]` section: Set `connection_type` to `serial`, `tcp`, or `ble` +- `[Bot]` section: Set `bot_latitude` and `bot_longitude` for your location +- `[Channels]` section: Set `monitor_channels` for channels to respond on + +### 3. Create Data Directories + +```bash +mkdir -p data logs +``` + +### 4. Start the Container + +```bash +docker-compose up -d +``` + +### 5. View Logs + +```bash +docker-compose logs -f +``` + +### 6. Access Web Viewer + +Open http://localhost:8080 in your browser. + +--- + +## Connection Types + +### Serial Connection (USB) + +Serial is the default connection type for direct USB connection to your MeshCore device. + +**Step 1: Identify your serial device** + +```bash +# Linux +ls -la /dev/ttyUSB* +# or +dmesg | grep tty + +# macOS +ls -la /dev/tty.usb* +``` + +**Step 2: Configure** + +Edit `config.ini`: +```ini +[Connection] +connection_type = serial +serial_port = /dev/ttyUSB0 +``` + +**Step 3: Enable device mapping** + +Edit `docker-compose.yml` and uncomment the devices section: + +```yaml +devices: + - "/dev/ttyUSB0:/dev/ttyUSB0" +``` + +If your device is different (e.g., `/dev/ttyACM0`), update the path accordingly: + +```yaml +devices: + - "/dev/ttyACM0:/dev/ttyACM0" +``` + +Then start the container: + +```bash +docker-compose up -d +``` + +**Permissions:** + +On Linux, you may need to add your user to the `dialout` group: +```bash +sudo usermod -aG dialout $USER +# Log out and back in for changes to take effect +``` + +--- + +### TCP Connection + +TCP is the simplest connection type when your MeshCore device is accessible over the network. + +**Configure:** + +```bash +# Set via environment variables +MESHCORE_CONNECTION_TYPE=tcp \ +MESHCORE_TCP_HOST=192.168.1.100 \ +MESHCORE_TCP_PORT=5000 \ +docker-compose up -d +``` + +Or edit `config.ini`: +```ini +[Connection] +connection_type = tcp +hostname = 192.168.1.100 +tcp_port = 5000 +``` + +--- + +### BLE (Bluetooth) Connection + +BLE connections require privileged access and host networking. + +**Step 1: Edit docker-compose.yml** + +Uncomment these lines: +```yaml +services: + meshcore-bot: + privileged: true + network_mode: host +``` + +**Step 2: Configure** + +```bash +MESHCORE_CONNECTION_TYPE=ble \ +MESHCORE_BLE_DEVICE=MeshCore \ +docker-compose up -d +``` + +**Note:** With `network_mode: host`, the web viewer is accessible directly on the host's port 8080 (port mapping is ignored). + +--- + +## Environment Variables + +All configuration can be overridden via environment variables: + +| Variable | Description | Default | +|----------|-------------|---------| +| `MESHCORE_CONNECTION_TYPE` | Connection type: serial, tcp, ble | serial | +| `MESHCORE_SERIAL_PORT` | Serial device path | /dev/ttyUSB0 | +| `MESHCORE_TCP_HOST` | TCP hostname or IP | - | +| `MESHCORE_TCP_PORT` | TCP port | 5000 | +| `MESHCORE_BLE_DEVICE` | BLE device name | - (auto-detect) | +| `MESHCORE_TIMEOUT` | Connection timeout (seconds) | 30 | +| `MESHCORE_BOT_NAME` | Bot identification name | - | +| `MESHCORE_LATITUDE` | Bot location latitude | - | +| `MESHCORE_LONGITUDE` | Bot location longitude | - | +| `MESHCORE_WEB_ENABLED` | Enable web viewer | true | +| `MESHCORE_WEB_PORT` | Web viewer port | 8080 | +| `TZ` | Timezone | UTC | +| `N2YO_API_KEY` | N2YO satellite API key | - | +| `AIRNOW_API_KEY` | AirNow AQI API key | - | +| `FORECAST_SOLAR_API_KEY` | Forecast.Solar API key | - | + +**Example with multiple environment variables:** + +```bash +TZ=America/Los_Angeles \ +MESHCORE_BOT_NAME=MyBot \ +MESHCORE_LATITUDE=47.6062 \ +MESHCORE_LONGITUDE=-122.3321 \ +docker-compose up -d +``` + +--- + +## Volume Mounts + +| Container Path | Purpose | Host Path | +|----------------|---------|-----------| +| `/app/config.ini` | Configuration file | `./config.ini` | +| `/app/data` | Database and persistent data | `./data` | +| `/app/logs` | Log files | `./logs` | + +--- + +## Docker Commands Reference + +### Build + +```bash +# Build the image +docker-compose build + +# Build without cache (for clean rebuild) +docker-compose build --no-cache +``` + +### Run + +```bash +# Start in detached mode +docker-compose up -d + +# Start with logs visible +docker-compose up + +# View logs +docker-compose logs -f + +# Stop +docker-compose down +``` + +### Maintenance + +```bash +# Restart +docker-compose restart + +# Update (rebuild and restart) +docker-compose up -d --build + +# Shell access +docker exec -it meshcore-bot /bin/bash + +# Database backup +docker exec meshcore-bot python backup_database.py + +# Check status +docker-compose ps +``` + +--- + +## Portainer Deployment + +Use the standalone compose file for Portainer or other container management platforms. + +### Using Portainer Stacks + +1. **Build the image first** (on the Docker host): + ```bash + git clone https://github.com/agessaman/meshcore-bot.git + cd meshcore-bot + docker build -t meshcore-bot:latest . + ``` + +2. **Create required files** on the host: + ```bash + # Create directories + mkdir -p /opt/meshcore-bot/data /opt/meshcore-bot/logs + + # Copy and edit config + cp config.ini.example /opt/meshcore-bot/config.ini + nano /opt/meshcore-bot/config.ini + ``` + +3. **In Portainer**, go to **Stacks** → **Add Stack** + +4. **Copy the contents** of `docker-compose.standalone.yml` into the web editor + +5. **Update the volume paths** to match your system: + ```yaml + volumes: + - /opt/meshcore-bot/config.ini:/app/config.ini:rw + - /opt/meshcore-bot/data:/app/data + - /opt/meshcore-bot/logs:/app/logs + ``` + +6. **For serial devices**, uncomment and configure: + ```yaml + devices: + - /dev/ttyUSB0:/dev/ttyUSB0 + ``` + +7. **Deploy the stack** + +### Standalone Compose File + +The `docker-compose.standalone.yml` file is designed for: +- Portainer Stacks +- Remote Docker hosts +- Container management platforms +- Environments without the full repository + +Key features: +- All configuration via environment variables +- Clear documentation in comments +- Pre-configured health checks +- Logging limits to prevent disk fill + +### Environment Variables in Portainer + +Instead of editing the compose file, you can set environment variables in Portainer's stack configuration: + +| Variable | Example Value | +|----------|---------------| +| `TZ` | `America/New_York` | +| `MESHCORE_CONNECTION_TYPE` | `serial` | +| `MESHCORE_SERIAL_PORT` | `/dev/ttyUSB0` | +| `MESHCORE_LATITUDE` | `47.6062` | +| `MESHCORE_LONGITUDE` | `-122.3321` | + +--- + +## NAS Deployment (Synology/QNAP) + +### Synology DSM + +1. **Install Docker** from Package Center + +2. **SSH into your NAS** and navigate to the project directory + +3. **Identify the serial device:** + ```bash + ls /dev/tty* + ``` + Common devices: `/dev/ttyUSB0`, `/dev/ttyACM0` + +4. **Build and run:** + ```bash + cd /volume1/docker/meshcore-bot + docker-compose build + SERIAL_DEVICE=/dev/ttyUSB0 docker-compose up -d + ``` + +### QNAP Container Station + +1. **Create a new container** using the built image or Dockerfile + +2. **Map the serial device** in Container Station settings + +3. **Mount volumes** for config, data, and logs + +--- + +## Troubleshooting + +### Container won't start + +```bash +# Check logs +docker-compose logs + +# Check if config is mounted correctly +docker exec meshcore-bot cat /app/config.ini + +# Check container status +docker-compose ps +``` + +### Serial device not found + +```bash +# Verify device exists on host +ls -la /dev/ttyUSB0 + +# Check if device is mapped +docker exec meshcore-bot ls -la /dev/ttyUSB0 + +# Check permissions +docker exec meshcore-bot stat /dev/ttyUSB0 + +# Try privileged mode (add to docker-compose.yml) +privileged: true +``` + +### Connection timeout + +```bash +# Increase timeout +MESHCORE_TIMEOUT=60 docker-compose up -d + +# Or edit config.ini +[Connection] +timeout = 60 +``` + +### Web viewer not accessible + +```bash +# Check if port is exposed +docker port meshcore-bot + +# Check if web viewer is enabled +docker exec meshcore-bot grep -A5 "\[Web_Viewer\]" /app/config.ini + +# Check container logs for Flask startup +docker-compose logs | grep -i flask +``` + +### Database issues + +```bash +# Check data directory permissions +ls -la ./data/ + +# Check inside container +docker exec meshcore-bot ls -la /app/data/ + +# Manually run database backup +docker exec meshcore-bot python backup_database.py +``` + +--- + +## Security Considerations + +1. **Web Viewer**: Has NO authentication built-in. Restrict access via: + - Firewall rules + - Reverse proxy with authentication + - Bind to localhost only (`MESHCORE_WEB_HOST=127.0.0.1`) + +2. **Config file**: Contains no secrets by default, but API keys may be sensitive + +3. **Serial access**: Requires root or dialout group membership + +4. **Privileged mode**: Required for BLE, gives container full host access + +--- + +## Manual Docker Run (without Compose) + +If you prefer not to use Docker Compose: + +```bash +# Build +docker build -t meshcore-bot:latest . + +# Run with serial device +docker run -d \ + --name meshcore-bot \ + --restart unless-stopped \ + --device /dev/ttyUSB0:/dev/ttyUSB0 \ + -v $(pwd)/config.ini:/app/config.ini:rw \ + -v $(pwd)/data:/app/data \ + -v $(pwd)/logs:/app/logs \ + -p 8080:8080 \ + -e TZ=America/New_York \ + -e MESHCORE_CONNECTION_TYPE=serial \ + meshcore-bot:latest + +# View logs +docker logs -f meshcore-bot + +# Stop +docker stop meshcore-bot +docker rm meshcore-bot +``` + +--- + +## Updating + +To update to a new version: + +```bash +# Pull latest code +git pull + +# Rebuild image +docker-compose build --no-cache + +# Restart with new image +docker-compose up -d +``` + +Your data and configuration will be preserved in the mounted volumes. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..1ca94b72 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,90 @@ +# ============================================ +# MeshCore Bot Dockerfile +# Supports: Serial, TCP, and BLE connections +# ============================================ + +# Build stage - install dependencies +FROM python:3.11-slim-bookworm AS builder + +WORKDIR /build + +# Install build dependencies for compiled packages +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc \ + python3-dev \ + && rm -rf /var/lib/apt/lists/* + +# Copy requirements and install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir --user -r requirements.txt + +# ============================================ +# Runtime stage +# ============================================ +FROM python:3.11-slim-bookworm AS runtime + +# Labels for image metadata +LABEL org.opencontainers.image.title="MeshCore Bot" +LABEL org.opencontainers.image.description="Python bot for MeshCore mesh networks" +LABEL org.opencontainers.image.source="https://github.com/agessaman/meshcore-bot" + +# Install runtime dependencies +# - libglib2.0-0: Required for BLE (bleak) +# - bluez: Bluetooth stack for BLE connections +# - dbus: D-Bus for BlueZ communication +RUN apt-get update && apt-get install -y --no-install-recommends \ + libglib2.0-0 \ + bluez \ + dbus \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Set working directory +WORKDIR /app + +# Copy Python packages from builder +COPY --from=builder /root/.local /root/.local + +# Copy application files +COPY meshcore_bot.py . +COPY modules/ ./modules/ +COPY translations/ ./translations/ +COPY config.ini.example . +COPY backup_database.py . + +# Copy entrypoint script +COPY docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +# Create directories for persistent data +RUN mkdir -p /app/data /app/logs + +# Add Python user packages to PATH +ENV PATH=/root/.local/bin:$PATH +ENV PYTHONUNBUFFERED=1 + +# Default environment variables (can be overridden) +ENV MESHCORE_CONNECTION_TYPE=serial +ENV MESHCORE_SERIAL_PORT=/dev/ttyUSB0 +ENV MESHCORE_TCP_HOST= +ENV MESHCORE_TCP_PORT=5000 +ENV MESHCORE_WEB_ENABLED=true +ENV MESHCORE_WEB_HOST=0.0.0.0 +ENV MESHCORE_WEB_PORT=8080 +ENV MESHCORE_WEB_AUTOSTART=true + +# Expose web viewer port +EXPOSE 8080 + +# Volume mount points +VOLUME ["/app/data", "/app/logs"] + +# Health check - verify Python process is running +HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ + CMD pgrep -f meshcore_bot.py || exit 1 + +# Set entrypoint +ENTRYPOINT ["/entrypoint.sh"] + +# Default command +CMD ["python", "meshcore_bot.py"] diff --git a/README.md b/README.md index 6bd6c2c8..a4f17053 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,57 @@ sudo systemctl status meshcore-bot See [SERVICE-INSTALLATION.md](SERVICE-INSTALLATION.md) for detailed service installation instructions. +### Docker Installation + +Run the bot in a Docker container for easy deployment on home servers, NAS systems, or cloud environments. + +**Quick Start:** +```bash +# 1. Copy and configure +cp config.ini.example config.ini +nano config.ini # Edit your settings + +# 2. Create data directories +mkdir -p data logs + +# 3. Build and run +docker-compose build +docker-compose up -d + +# 4. View logs +docker-compose logs -f +``` + +**Serial Device (Linux/NAS):** +```bash +# Edit docker-compose.yml and uncomment the devices section: +# devices: +# - "/dev/ttyUSB0:/dev/ttyUSB0" +# Then run: +docker-compose up -d +``` + +**TCP Connection:** +```bash +MESHCORE_CONNECTION_TYPE=tcp \ +MESHCORE_TCP_HOST=192.168.1.100 \ +docker-compose up -d +``` + +**Environment Variables:** +| Variable | Description | Default | +|----------|-------------|---------| +| `MESHCORE_CONNECTION_TYPE` | serial, tcp, or ble | serial | +| `MESHCORE_SERIAL_PORT` | Serial device path | /dev/ttyUSB0 | +| `MESHCORE_TCP_HOST` | TCP hostname/IP | - | +| `MESHCORE_TCP_PORT` | TCP port | 5000 | +| `MESHCORE_WEB_PORT` | Web viewer port | 8080 | +| `TZ` | Timezone | UTC | + +**Web Viewer:** Access at http://localhost:8080 + +See [DOCKER.md](DOCKER.md) for complete Docker documentation including NAS deployment, BLE setup, and troubleshooting. + ## Configuration The bot uses `config.ini` for all settings. Key configuration sections: diff --git a/docker-compose.standalone.yml b/docker-compose.standalone.yml new file mode 100644 index 00000000..93398a14 --- /dev/null +++ b/docker-compose.standalone.yml @@ -0,0 +1,145 @@ +# ============================================ +# MeshCore Bot - Standalone Docker Compose +# ============================================ +# For use with Portainer, Synology, QNAP, or any Docker environment +# +# USAGE: +# 1. Copy this file to your Docker host +# 2. Create a 'config.ini' file (copy from config.ini.example) +# 3. Deploy via Portainer Stack or: docker-compose -f docker-compose.standalone.yml up -d +# +# IMAGE OPTIONS: +# - Build locally: docker build -t meshcore-bot:latest . +# - Or use a published image (update 'image' field below) +# +# VOLUME PATHS: +# Update the volume paths under 'volumes' to match your system +# ============================================ + +version: "3.8" + +services: + meshcore-bot: + # Option 1: Use locally built image + image: meshcore-bot:latest + + # Option 2: Use published image (uncomment and update) + # image: ghcr.io/agessaman/meshcore-bot:latest + + container_name: meshcore-bot + restart: unless-stopped + + # ============================================ + # ENVIRONMENT CONFIGURATION + # These override settings in config.ini + # ============================================ + environment: + # Timezone (use tz database names: America/New_York, Europe/London, etc.) + - TZ=UTC + + # ---------------------------------------- + # CONNECTION SETTINGS (Required) + # ---------------------------------------- + # Connection type: serial, tcp, or ble + - MESHCORE_CONNECTION_TYPE=serial + + # Serial port (for serial connection) + - MESHCORE_SERIAL_PORT=/dev/ttyUSB0 + + # TCP settings (for tcp connection) + # - MESHCORE_TCP_HOST=192.168.1.100 + # - MESHCORE_TCP_PORT=5000 + + # BLE device name (for ble connection) + # - MESHCORE_BLE_DEVICE=MeshCore + + # Connection timeout in seconds + - MESHCORE_TIMEOUT=30 + + # ---------------------------------------- + # BOT SETTINGS (Optional) + # ---------------------------------------- + # Bot name for identification + # - MESHCORE_BOT_NAME=MeshCoreBot + + # Bot location (for weather, solar calculations) + # - MESHCORE_LATITUDE=40.7128 + # - MESHCORE_LONGITUDE=-74.0060 + + # ---------------------------------------- + # WEB VIEWER SETTINGS + # ---------------------------------------- + - MESHCORE_WEB_ENABLED=true + - MESHCORE_WEB_HOST=0.0.0.0 + - MESHCORE_WEB_PORT=8080 + - MESHCORE_WEB_AUTOSTART=true + + # ---------------------------------------- + # API KEYS (Optional - for extended features) + # ---------------------------------------- + # Satellite pass data (https://www.n2yo.com/login/) + # - N2YO_API_KEY=your_api_key + + # Air quality data (https://docs.airnowapi.org/) + # - AIRNOW_API_KEY=your_api_key + + # Solar forecast (https://forecast.solar/) + # - FORECAST_SOLAR_API_KEY=your_api_key + + # ============================================ + # VOLUME MOUNTS + # Update paths to match your system + # ============================================ + volumes: + # Configuration file (required) + # Create from config.ini.example before first run + - /path/to/your/config.ini:/app/config.ini:rw + + # Persistent data directory (database, cache) + - /path/to/your/data:/app/data + + # Log files (optional) + - /path/to/your/logs:/app/logs + + # ============================================ + # NETWORK SETTINGS + # ============================================ + ports: + # Web viewer port (host:container) + - "8080:8080" + + # ============================================ + # DEVICE MAPPING (for Serial/USB connection) + # Uncomment and adjust for your device + # ============================================ + # devices: + # - /dev/ttyUSB0:/dev/ttyUSB0 + # # Common alternatives: + # # - /dev/ttyACM0:/dev/ttyUSB0 + # # - /dev/serial/by-id/usb-xyz:/dev/ttyUSB0 + + # ============================================ + # PRIVILEGED MODE (for BLE connection) + # Required for Bluetooth access + # ============================================ + # privileged: true + # network_mode: host # Also required for BLE + + # ============================================ + # HEALTH CHECK + # ============================================ + healthcheck: + test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8080/')\" || exit 1"] + interval: 30s + timeout: 30s + retries: 3 + start_period: 30s + + # ============================================ + # LOGGING + # ============================================ + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..7b71d942 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,94 @@ +# ============================================ +# MeshCore Bot Docker Compose Configuration +# ============================================ +# Quick Start: +# 1. cp config.ini.example config.ini +# 2. Edit config.ini with your settings +# 3. docker-compose up -d +# +# For different connection types, set MESHCORE_CONNECTION_TYPE: +# Serial: MESHCORE_CONNECTION_TYPE=serial (default) +# TCP: MESHCORE_CONNECTION_TYPE=tcp MESHCORE_TCP_HOST=192.168.1.100 +# BLE: MESHCORE_CONNECTION_TYPE=ble (requires privileged mode) +# ============================================ + +services: + meshcore-bot: + build: + context: . + dockerfile: Dockerfile + image: meshcore-bot:latest + container_name: meshcore-bot + restart: unless-stopped + + # Environment variables for configuration + # These override values in config.ini + environment: + # Timezone (use standard tz database names) + - TZ=${TZ:-UTC} + + # Connection settings + - MESHCORE_CONNECTION_TYPE=${MESHCORE_CONNECTION_TYPE:-serial} + - MESHCORE_SERIAL_PORT=${MESHCORE_SERIAL_PORT:-/dev/ttyUSB0} + - MESHCORE_TCP_HOST=${MESHCORE_TCP_HOST:-} + - MESHCORE_TCP_PORT=${MESHCORE_TCP_PORT:-5000} + - MESHCORE_BLE_DEVICE=${MESHCORE_BLE_DEVICE:-} + - MESHCORE_TIMEOUT=${MESHCORE_TIMEOUT:-30} + + # Bot settings + - MESHCORE_BOT_NAME=${MESHCORE_BOT_NAME:-} + - MESHCORE_LATITUDE=${MESHCORE_LATITUDE:-} + - MESHCORE_LONGITUDE=${MESHCORE_LONGITUDE:-} + + # Web viewer settings + - MESHCORE_WEB_ENABLED=${MESHCORE_WEB_ENABLED:-true} + - MESHCORE_WEB_HOST=0.0.0.0 + - MESHCORE_WEB_PORT=${MESHCORE_WEB_PORT:-8080} + - MESHCORE_WEB_AUTOSTART=${MESHCORE_WEB_AUTOSTART:-true} + + # API keys (optional) + - N2YO_API_KEY=${N2YO_API_KEY:-} + - AIRNOW_API_KEY=${AIRNOW_API_KEY:-} + - FORECAST_SOLAR_API_KEY=${FORECAST_SOLAR_API_KEY:-} + + # Volume mounts for persistent data + volumes: + # Configuration file - mount your config.ini here + - ./config.ini:/app/config.ini:rw + # Persistent data (database) + - ./data:/app/data + # Log files + - ./logs:/app/logs + + # Web viewer port + ports: + - "${WEB_PORT:-8080}:8080" + + # Serial device mapping (for USB connection on Linux) + # NOTE: Docker on macOS cannot passthrough serial devices directly. + # For macOS development, use TCP connection instead. + # For Linux/NAS deployment, uncomment the devices section below. + # devices: + # - "${SERIAL_DEVICE:-/dev/ttyUSB0}:/dev/ttyUSB0" + + # Alternative: Use privileged mode for broader device access + # Required for BLE connections + # privileged: true + + # For BLE connections, you also need host networking + # network_mode: host + + # Health check + healthcheck: + test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8080/')\" || exit 1"] + interval: 30s + timeout: 30s + retries: 3 + start_period: 30s + + # Logging configuration + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 00000000..1fb0e0d3 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,154 @@ +#!/bin/bash +# ============================================ +# MeshCore Bot Docker Entrypoint +# ============================================ + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# ============================================ +# Configuration Setup +# ============================================ + +# Check if config.ini exists, if not copy from example +if [ ! -f /app/config.ini ]; then + if [ -f /app/config.ini.example ]; then + log_warn "No config.ini found, copying from config.ini.example" + cp /app/config.ini.example /app/config.ini + else + log_error "No config.ini or config.ini.example found!" + exit 1 + fi +fi + +# ============================================ +# Environment Variable Overrides +# Apply environment variables to config.ini +# ============================================ + +apply_config_override() { + local section=$1 + local key=$2 + local value=$3 + local config_file="/app/config.ini" + + if [ -n "$value" ]; then + log_info "Setting [${section}] ${key} = ${value}" + # Use Python for reliable INI file editing + python3 -c " +import configparser +config = configparser.ConfigParser() +config.read('${config_file}') +if not config.has_section('${section}'): + config.add_section('${section}') +config.set('${section}', '${key}', '${value}') +with open('${config_file}', 'w') as f: + config.write(f) +" + fi +} + +# Apply connection settings from environment +apply_config_override "Connection" "connection_type" "${MESHCORE_CONNECTION_TYPE}" +apply_config_override "Connection" "serial_port" "${MESHCORE_SERIAL_PORT}" +apply_config_override "Connection" "hostname" "${MESHCORE_TCP_HOST}" +apply_config_override "Connection" "tcp_port" "${MESHCORE_TCP_PORT}" +apply_config_override "Connection" "ble_device_name" "${MESHCORE_BLE_DEVICE}" +apply_config_override "Connection" "timeout" "${MESHCORE_TIMEOUT}" + +# Apply bot settings from environment +apply_config_override "Bot" "bot_name" "${MESHCORE_BOT_NAME}" +apply_config_override "Bot" "timezone" "${TZ}" +apply_config_override "Bot" "bot_latitude" "${MESHCORE_LATITUDE}" +apply_config_override "Bot" "bot_longitude" "${MESHCORE_LONGITUDE}" + +# Apply web viewer settings from environment +apply_config_override "Web_Viewer" "enabled" "${MESHCORE_WEB_ENABLED}" +apply_config_override "Web_Viewer" "host" "${MESHCORE_WEB_HOST}" +apply_config_override "Web_Viewer" "port" "${MESHCORE_WEB_PORT}" +apply_config_override "Web_Viewer" "auto_start" "${MESHCORE_WEB_AUTOSTART}" + +# Apply API keys from environment +apply_config_override "External_Data" "n2yo_api_key" "${N2YO_API_KEY}" +apply_config_override "External_Data" "airnow_api_key" "${AIRNOW_API_KEY}" +apply_config_override "External_Data" "forecast_solar_api_key" "${FORECAST_SOLAR_API_KEY}" + +# ============================================ +# Serial-specific Setup +# ============================================ + +if [ "${MESHCORE_CONNECTION_TYPE}" = "serial" ]; then + SERIAL_DEVICE="${MESHCORE_SERIAL_PORT:-/dev/ttyUSB0}" + log_info "Serial mode detected, checking device: $SERIAL_DEVICE" + + if [ -c "$SERIAL_DEVICE" ]; then + log_info "Serial device $SERIAL_DEVICE is available" + # Ensure proper permissions + chmod 666 "$SERIAL_DEVICE" 2>/dev/null || log_warn "Could not set permissions on $SERIAL_DEVICE" + else + log_warn "Serial device $SERIAL_DEVICE not found, connection may fail" + log_warn "Make sure the device is mapped with --device flag" + fi +fi + +# ============================================ +# BLE-specific Setup +# ============================================ + +if [ "${MESHCORE_CONNECTION_TYPE}" = "ble" ]; then + log_info "BLE mode detected, checking Bluetooth availability..." + + # Check if BlueZ is available + if command -v bluetoothctl &> /dev/null; then + log_info "BlueZ available" + # Start D-Bus if not running (needed for BlueZ) + if [ ! -S /var/run/dbus/system_bus_socket ]; then + log_warn "D-Bus socket not found, BLE may not work correctly" + fi + else + log_warn "BlueZ not available, BLE connection may fail" + fi +fi + +# ============================================ +# Data Directory Setup +# ============================================ + +# Ensure data directory exists and is writable +if [ ! -d /app/data ]; then + log_info "Creating data directory" + mkdir -p /app/data +fi + +# Ensure logs directory exists +if [ ! -d /app/logs ]; then + log_info "Creating logs directory" + mkdir -p /app/logs +fi + +# ============================================ +# Start the Bot +# ============================================ + +log_info "Starting MeshCore Bot..." +log_info "Connection type: ${MESHCORE_CONNECTION_TYPE:-default from config}" + +# Execute the main command (default: python meshcore_bot.py) +exec "$@" diff --git a/requirements.txt b/requirements.txt index d5bf6a38..92135fb3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,3 +19,4 @@ flask>=2.3.0 flask-socketio>=5.3.0 meshcore-cli feedparser>=6.0.10 +cryptography>=41.0.0