diff --git a/.env.example b/.env.example index 8db40a1..ba9409f 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,6 @@ +# Copyright © 2025-26 l5yth & contributors +# Licensed under the Apache License, Version 2.0 (see LICENSE) +# # PotatoMesh Environment Configuration # Copy this file to .env and customize for your setup @@ -14,7 +17,7 @@ INSTANCE_DOMAIN="mesh.example.org" # Generate a secure token: openssl rand -hex 32 API_TOKEN="your-secure-api-token-here" -# Meshtastic connection target (required for ingestor) +# Mesh radio connection target (required for ingestor) # Common serial paths: # - Linux: /dev/ttyACM0, /dev/ttyUSB0 # - macOS: /dev/cu.usbserial-* @@ -23,6 +26,10 @@ API_TOKEN="your-secure-api-token-here" # Bluetooth address (e.g. ED:4D:9E:95:CF:60). CONNECTION="/dev/ttyACM0" +# Mesh protocol to use (meshtastic or meshcore) +# Default: meshtastic +PROTOCOL="meshtastic" + # ============================================================================= # SITE CUSTOMIZATION # ============================================================================= @@ -68,6 +75,9 @@ PRIVATE=0 # Debug mode (0=off, 1=on) DEBUG=0 +# Energy saving mode — sleep between ingestion cycles (0=off, 1=on) +ENERGY_SAVING=0 + # Default map zoom override # MAP_ZOOM=15 diff --git a/.github/workflows/README.md b/.github/workflows/README.md index eba4fd5..65534bf 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -1,3 +1,6 @@ + + + # GitHub Actions Workflows ## Workflows diff --git a/CHANGELOG.md b/CHANGELOG.md index d51895e..b42c51c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,20 @@ + + + # CHANGELOG ## v0.6.0 +**Official multi-protocol release.** This version introduces first-class +support for both Meshtastic and MeshCore mesh protocols via the new `PROTOCOL` +environment variable. Key additions since v0.5.12: + +* Feat: official MeshCore provider with BLE, TCP, and serial support +* Feat: multi-protocol awareness across web frontend, ingestor, and mobile app +* Enh: surface MeshCore role types and distinguish protocols in the UI + +See v0.5.12 below for the full commit history of multi-protocol groundwork. + **Breaking changes — remove deprecated environment variable aliases:** * Ingestor: remove `POTATOMESH_INSTANCE` env var — use `INSTANCE_DOMAIN` by @l5yth diff --git a/CLAUDE.md b/CLAUDE.md index 1485cbb..0533370 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,9 @@ + + + # Repository Guidelines -Keep code as modular as possible to reduce duplication and improve reusability and readability. If a module grows large, split it into a submodule structure. Prefer composing small, single-purpose units over monolithic files. +Keep code as modular as possible to reduce duplication and improve reusability and readability — this applies to tests as well as production code. If a module grows large, split it into a submodule structure. Prefer composing small, single-purpose units over monolithic files. Make sure all tests pass for Python (`pytest`), Ruby (`rspec`), and JavaScript (`npm test`). @@ -8,7 +11,7 @@ All code must be 100% unit tested — every line, branch, and code path must hav All code must be 100% documented according to the language's API-doc standard (PDoc for Python, RDoc for Ruby, JSDoc for JavaScript, rustdoc for Rust, dartdoc for Dart). Documentation must be sufficient to generate complete API docs from source. In addition to API-level docs, add inline comments wherever the logic is not immediately self-evident. -New source files should have Apache v2 license headers using the exact string `Copyright © 2025-26 l5yth & contributors`. +Every file in the repository must carry an Apache v2 license notice using the exact string `Copyright © 2025-26 l5yth & contributors`. **Source-code files** (`.rb`, `.py`, `.js`, `.rs`, `.dart`, etc.) must include the full Apache v2 license header block. **Non-source files** (docs, configs, YAML, TOML, Dockerfiles, etc.) must include a short 2-line Apache v2 notice (copyright line + license reference). Run linters for Python (`black`) and Ruby (`rufo`) to ensure consistent code formatting. diff --git a/DOCKER.md b/DOCKER.md index 02923ac..1c917b0 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -1,3 +1,6 @@ + + + # PotatoMesh Docker Guide PotatoMesh publishes ready-to-run container images to the GitHub Packages container diff --git a/Dockerfile b/Dockerfile index ae80977..b307752 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1.6 # Copyright © 2025-26 l5yth & contributors # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -25,6 +26,9 @@ ENV BUNDLE_FORCE_RUBY_PLATFORM=true # Install build dependencies and SQLite3 RUN apk add --no-cache \ build-base \ + python3 \ + py3-pip \ + py3-virtualenv \ sqlite-dev \ linux-headers \ pkgconfig @@ -40,11 +44,16 @@ RUN bundle config set --local force_ruby_platform true && \ bundle config set --local without 'development test' && \ bundle install --jobs=4 --retry=3 +# Install Meshtastic decoder dependencies in a dedicated venv +RUN python3 -m venv /opt/meshtastic-venv && \ + /opt/meshtastic-venv/bin/pip install --no-cache-dir meshtastic protobuf + # Production stage FROM ruby:3.3-alpine AS production # Install runtime dependencies RUN apk add --no-cache \ + python3 \ sqlite \ tzdata \ curl @@ -58,18 +67,27 @@ WORKDIR /app # Copy installed gems from builder stage COPY --from=builder /usr/local/bundle /usr/local/bundle +COPY --from=builder /opt/meshtastic-venv /opt/meshtastic-venv -# Copy application code (exclude Dockerfile from web directory) -COPY --chown=potatomesh:potatomesh web/app.rb web/app.sh web/Gemfile web/Gemfile.lock* web/spec/ ./ +# Copy application code (excluding the Dockerfile which is not required at runtime) +COPY --chown=potatomesh:potatomesh web/app.rb ./ +COPY --chown=potatomesh:potatomesh web/app.sh ./ +COPY --chown=potatomesh:potatomesh web/Gemfile ./ +COPY --chown=potatomesh:potatomesh web/Gemfile.lock* ./ +COPY --chown=potatomesh:potatomesh web/lib ./lib +COPY --chown=potatomesh:potatomesh web/spec ./spec COPY --chown=potatomesh:potatomesh web/public ./public -COPY --chown=potatomesh:potatomesh web/views/ ./views/ +COPY --chown=potatomesh:potatomesh web/views ./views +COPY --chown=potatomesh:potatomesh web/scripts ./scripts # Copy SQL schema files from data directory COPY --chown=potatomesh:potatomesh data/*.sql /data/ +COPY --chown=potatomesh:potatomesh data/mesh_ingestor/decode_payload.py /app/data/mesh_ingestor/decode_payload.py -# Create data directory for SQLite database -RUN mkdir -p /app/data /app/.local/share/potato-mesh && \ - chown -R potatomesh:potatomesh /app/data /app/.local +# Create data and configuration directories with correct ownership +RUN mkdir -p /app/.local/share/potato-mesh \ + && mkdir -p /app/.config/potato-mesh/well-known \ + && chown -R potatomesh:potatomesh /app/.local/share /app/.config # Switch to non-root user USER potatomesh @@ -78,13 +96,16 @@ USER potatomesh EXPOSE 41447 # Default environment variables (can be overridden by host) -ENV APP_ENV=production \ - RACK_ENV=production \ +ENV RACK_ENV=production \ + APP_ENV=production \ + MESHTASTIC_PYTHON=/opt/meshtastic-venv/bin/python \ + XDG_DATA_HOME=/app/.local/share \ + XDG_CONFIG_HOME=/app/.config \ SITE_NAME="PotatoMesh Demo" \ - INSTANCE_DOMAIN="potato.example.com" \ CHANNEL="#LongFast" \ FREQUENCY="915MHz" \ MAP_CENTER="38.761944,-27.090833" \ + MAP_ZOOM="" \ MAX_DISTANCE=42 \ CONTACT_LINK="#potatomesh:dod.ngo" \ DEBUG=0 diff --git a/PROMETHEUS.md b/PROMETHEUS.md index 0b29a9c..51b8e27 100644 --- a/PROMETHEUS.md +++ b/PROMETHEUS.md @@ -1,3 +1,6 @@ + + + # Prometheus Monitoring for PotatoMesh PotatoMesh exposes runtime telemetry through a dedicated Prometheus endpoint so you can diff --git a/README.md b/README.md index c4afee5..4af89bb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ + + + # 🥔 PotatoMesh [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/l5yth/potato-mesh/ruby.yml?branch=main)](https://github.com/l5yth/potato-mesh/actions) @@ -30,7 +33,7 @@ _No MQTT clutter, just local LoRa aether._ Live demo for Berlin: [potatomesh.net](https://potatomesh.net) -![screenshot of the fourth version](./scrot-0.4.png) +![screenshot of the sixth version](./scrot-0.7.png) ## Web App @@ -275,9 +278,9 @@ docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-arm64:latest docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-armv7:latest # version-pinned examples -docker pull ghcr.io/l5yth/potato-mesh-web-linux-amd64:v0.5.5 -docker pull ghcr.io/l5yth/potato-mesh-ingestor-linux-amd64:v0.5.5 -docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-amd64:v0.5.5 +docker pull ghcr.io/l5yth/potato-mesh-web-linux-amd64:v0.6.0 +docker pull ghcr.io/l5yth/potato-mesh-ingestor-linux-amd64:v0.6.0 +docker pull ghcr.io/l5yth/potato-mesh-matrix-bridge-linux-amd64:v0.6.0 ``` Note: `latest` is only published for non-prerelease versions. Pre-release tags diff --git a/app/README.md b/app/README.md index 85e2548..621a952 100644 --- a/app/README.md +++ b/app/README.md @@ -1,6 +1,10 @@ -# Meshtastic Reader + + -Meshtastic Reader – read-only PotatoMesh chat client for Android and iOS. +# PotatoMesh Mobile + +PotatoMesh Mobile — read-only mesh chat client for Android and iOS. +Supports Meshtastic and MeshCore networks. ## Setup diff --git a/data/Dockerfile b/data/Dockerfile index 6630b8d..fe84a59 100644 --- a/data/Dockerfile +++ b/data/Dockerfile @@ -50,6 +50,7 @@ USER potatomesh ENV CONNECTION=/dev/ttyACM0 \ CHANNEL_INDEX=0 \ DEBUG=0 \ + PROTOCOL=meshtastic \ ALLOWED_CHANNELS="" \ HIDDEN_CHANNELS="" \ INSTANCE_DOMAIN="" \ @@ -77,6 +78,7 @@ USER ContainerUser ENV CONNECTION=/dev/ttyACM0 \ CHANNEL_INDEX=0 \ DEBUG=0 \ + PROTOCOL=meshtastic \ ALLOWED_CHANNELS="" \ HIDDEN_CHANNELS="" \ INSTANCE_DOMAIN="" \ diff --git a/data/mesh_ingestor/CONTRACTS.md b/data/mesh_ingestor/CONTRACTS.md index 2afc565..99c8bbe 100644 --- a/data/mesh_ingestor/CONTRACTS.md +++ b/data/mesh_ingestor/CONTRACTS.md @@ -1,3 +1,6 @@ + + + ## Mesh ingestor contracts (stable interfaces) This repo’s ingestion pipeline is split into: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index a0800be..d817954 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -49,3 +49,21 @@ services: environment: DEBUG: 0 restart: always + + matrix-bridge: + build: + context: . + dockerfile: matrix/Dockerfile + target: runtime + environment: + DEBUG: 0 + restart: always + + matrix-bridge-bridge: + build: + context: . + dockerfile: matrix/Dockerfile + target: runtime + environment: + DEBUG: 0 + restart: always diff --git a/docker-compose.yml b/docker-compose.yml index 88468cf..6bffd42 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,6 +54,8 @@ x-ingestor-base: &ingestor-base API_TOKEN: ${API_TOKEN} INSTANCE_DOMAIN: ${INSTANCE_DOMAIN:-http://web:41447} DEBUG: ${DEBUG:-0} + PROTOCOL: ${PROTOCOL:-meshtastic} + ENERGY_SAVING: ${ENERGY_SAVING:-0} FEDERATION: ${FEDERATION:-1} PRIVATE: ${PRIVATE:-0} volumes: diff --git a/matrix/README.md b/matrix/README.md index 147159c..71cd706 100644 --- a/matrix/README.md +++ b/matrix/README.md @@ -1,3 +1,6 @@ + + + # potatomesh-matrix-bridge A small Rust daemon that bridges **PotatoMesh** LoRa messages into a **Matrix** room. @@ -90,7 +93,7 @@ room_id = "!yourroomid:example.org" [state] # Where to persist last seen message id state_file = "bridge_state.json" -```` +``` The `hs_token` is used to validate inbound appservice transactions. Keep it identical in `Config.toml` and your Matrix appservice registration file. diff --git a/scrot-0.7.png b/scrot-0.7.png new file mode 100644 index 0000000..6121381 Binary files /dev/null and b/scrot-0.7.png differ