mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-05-08 06:24:27 +02:00
481 lines
17 KiB
Plaintext
481 lines
17 KiB
Plaintext
# Default Repeater Configuration
|
||
# radio_type: sx1262 | kiss (use kiss for serial KISS TNC modem)
|
||
radio_type: sx1262
|
||
|
||
repeater:
|
||
# Node name for logging and identification
|
||
node_name: "mesh-repeater-01"
|
||
|
||
# TX mode: forward | monitor | no_tx (default: forward)
|
||
# forward = repeat on; monitor = no repeat but companions/tenants can send; no_tx = all TX off
|
||
# mode: forward
|
||
|
||
# Geographic location (optional)
|
||
# Latitude in decimal degrees (-90 to 90)
|
||
latitude: 0.0
|
||
# Longitude in decimal degrees (-180 to 180)
|
||
longitude: 0.0
|
||
|
||
# Path to identity file (public/private key)
|
||
# If not specified, a new identity will be generated
|
||
identity_file: null
|
||
|
||
# Identity key (alternative to identity_file)
|
||
# Store the private key directly in config as binary (set by convert_firmware_key.sh)
|
||
# If both identity_file and identity_key are set, identity_key takes precedence
|
||
# identity_key: null
|
||
|
||
# Owner information (shown to clients requesting owner info)
|
||
owner_info: ""
|
||
|
||
# Duplicate packet cache TTL in seconds
|
||
cache_ttl: 3600
|
||
|
||
# Maximum number of hops a flood packet may have already traversed before
|
||
# this repeater forwards it.
|
||
max_flood_hops: 64
|
||
|
||
# Score-based transmission filtering
|
||
# Enable quality-based packet filtering and adaptive delays
|
||
use_score_for_tx: false
|
||
|
||
# Score threshold for quality monitoring (future use)
|
||
# Currently reserved for potential future features like dashboard alerts,
|
||
# proactive statistics collection, or advanced filtering strategies.
|
||
# Changing this value has no effect on current packet processing.
|
||
score_threshold: 0.3
|
||
|
||
# Automatic advertisement interval in hours
|
||
# The repeater will send an advertisement packet at this interval
|
||
# Set to 0 to disable automatic adverts (manual only via web interface)
|
||
# Range: 0 (disabled) to 24+ hours
|
||
# Recommended: 10 hours for typical deployments
|
||
send_advert_interval_hours: 10
|
||
|
||
# Respond to discovery requests from other nodes
|
||
# When enabled, the repeater will automatically respond to discovery packets
|
||
# with its node information (node type 2 - repeater)
|
||
allow_discovery: true
|
||
|
||
# Incoming advert rate limiter (per advert public key)
|
||
# Uses a token bucket to smooth bursts.
|
||
advert_rate_limit:
|
||
# Master switch for token bucket limiting
|
||
enabled: false
|
||
# Max burst size allowed immediately per pubkey
|
||
# Keep this small for long advert intervals.
|
||
bucket_capacity: 2
|
||
# Number of tokens added each refill interval
|
||
refill_tokens: 1
|
||
# Refill interval in seconds (10 hours)
|
||
refill_interval_seconds: 36000
|
||
# Optional hard minimum spacing between adverts from same pubkey
|
||
# Set 0 to disable (recommended - mesh retransmissions are normal in active networks)
|
||
min_interval_seconds: 0
|
||
|
||
# Penalty box for repeat advert limit violations (per pubkey)
|
||
advert_penalty_box:
|
||
# Master switch for escalating cooldowns
|
||
enabled: false
|
||
# Number of violations within decay window before cooldown starts
|
||
violation_threshold: 2
|
||
# Reset violation count if pubkey stays quiet for this long
|
||
violation_decay_seconds: 43200
|
||
# First penalty duration in seconds
|
||
base_penalty_seconds: 21600
|
||
# Exponential growth factor for repeated violations
|
||
penalty_multiplier: 2.0
|
||
# Maximum penalty duration cap
|
||
max_penalty_seconds: 86400
|
||
|
||
# Adaptive rate limiting based on mesh activity
|
||
# Rate limits scale with mesh busyness: quiet mesh = lenient, busy mesh = strict
|
||
advert_adaptive:
|
||
# Master switch for adaptive scaling
|
||
enabled: false
|
||
# EWMA smoothing factor (0.0-1.0, higher = faster response)
|
||
ewma_alpha: 0.1
|
||
# Seconds without metrics change before tier change takes effect (hysteresis)
|
||
hysteresis_seconds: 300
|
||
# Tier thresholds based on adverts per minute EWMA
|
||
thresholds:
|
||
quiet_max: 0.05 # Below this = QUIET tier (no limiting)
|
||
normal_max: 0.20 # Below this = NORMAL tier (1x limits)
|
||
busy_max: 0.50 # Below this = BUSY tier (0.5x capacity)
|
||
# Above busy_max = CONGESTED tier (0.25x capacity)
|
||
|
||
# Security settings for login/authentication (shared across all identities)
|
||
security:
|
||
# Maximum number of authenticated clients (across all identities)
|
||
max_clients: 1
|
||
|
||
# Admin password for full access
|
||
admin_password: "admin123"
|
||
|
||
# Guest password for limited access
|
||
guest_password: "guest123"
|
||
|
||
# Allow read-only access for clients without password/not in ACL
|
||
allow_read_only: false
|
||
|
||
# JWT secret key for signing tokens (auto-generated if not provided)
|
||
# Generate with: python -c "import secrets; print(secrets.token_hex(32))"
|
||
jwt_secret: ""
|
||
|
||
# JWT token expiry time in minutes (default: 60 minutes / 1 hour)
|
||
# Controls how long users stay logged in before needing to re-authenticate
|
||
jwt_expiry_minutes: 60
|
||
|
||
# Local GPS receiver. When enabled, the daemon reads NMEA sentences from the
|
||
# configured source and exposes parsed data at /api/gps.
|
||
gps:
|
||
enabled: false
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Source
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# Source type:
|
||
# serial = read directly from an attached GPS module
|
||
# file = read NMEA lines from source_path (useful for gpsd/sidecar bridges)
|
||
source: serial
|
||
|
||
# Serial source settings (used when source: serial)
|
||
device: "/dev/serial0"
|
||
baud_rate: 9600
|
||
read_timeout_seconds: 1.0
|
||
reconnect_interval_seconds: 5.0
|
||
|
||
# File source settings (used when source: file)
|
||
# The file may contain raw NMEA lines or JSON with a "sentences" list /
|
||
# "last_sentence" field.
|
||
source_path: "/var/lib/pymc_repeater/gps_nmea.txt"
|
||
poll_interval_seconds: 2.0
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Location behaviour
|
||
# Three independent controls — read the comments carefully, they do
|
||
# different things:
|
||
#
|
||
# api_fallback_to_config_location — what the API *displays* before a fix
|
||
# advertise_gps_location — what the mesh *advertises* in adverts
|
||
# persist_gps_fix_to_config — whether the fix is *written* to config
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# API display: while GPS has no valid fix, show repeater.latitude/longitude
|
||
# from config in the /api/gps effective position instead of null/0,0.
|
||
# The default 0,0 repeater location is treated as unset (no fallback shown).
|
||
# Has no effect on mesh adverts or config persistence.
|
||
api_fallback_to_config_location: true
|
||
|
||
# Mesh adverts: use GPS coordinates in repeater-originated location fields
|
||
# (flood adverts, etc.). When false, repeater.latitude/longitude from config
|
||
# are always used for outgoing mesh packets.
|
||
advertise_gps_location: false
|
||
|
||
# Config persistence: write a valid GPS fix back into repeater.latitude/
|
||
# repeater.longitude so adverts location details follow the
|
||
# receiver across restarts. Updates are throttled to avoid rewriting config
|
||
# on every NMEA sentence. location_precision_digits is applied before saving.
|
||
persist_gps_fix_to_config: false
|
||
persist_gps_fix_interval_seconds: 600.0
|
||
|
||
# Optional privacy/obfuscation: round coordinates to this many decimal places
|
||
# before they are used for advertising or persisted to config (0–8).
|
||
# Leave null for full precision. Affects both advertise_gps_location and
|
||
# persist_gps_fix_to_config.
|
||
location_precision_digits: null
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Diagnostics
|
||
# ---------------------------------------------------------------------------
|
||
|
||
stale_after_seconds: 10.0
|
||
retain_sentences: 25
|
||
validate_checksum: true
|
||
require_checksum: false
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# Time sync
|
||
# ---------------------------------------------------------------------------
|
||
|
||
# Automatically set the Linux system clock from GPS UTC time once the
|
||
# receiver has a valid non-stale fix. The systemd service grants
|
||
# CAP_SYS_TIME for this.
|
||
time_sync_enabled: true
|
||
time_sync_interval_seconds: 3600.0
|
||
time_sync_min_offset_seconds: 1.0
|
||
time_sync_min_valid_year: 2020
|
||
|
||
# Mesh Network Configuration
|
||
mesh:
|
||
# Unscoped flood policy - controls whether the repeater allows or denies unscoped flooding
|
||
# true = allow unscoped flooding, false = deny flooding globally
|
||
unscoped_flood_allow: true
|
||
|
||
# Path hash mode for flood packets (0-hop): per-hop hash size in path encoding
|
||
# 0 = 1-byte hashes (legacy), 1 = 2-byte, 2 = 3-byte. Must match mesh convention.
|
||
# Affects originated adverts and any other flood packets sent by the repeater.
|
||
path_hash_mode: 0
|
||
|
||
# Flood loop detection mode
|
||
# off = disabled, minimal = allow up to 3 self-hashes, moderate = allow up to 1, strict = allow 0
|
||
loop_detect: minimal
|
||
|
||
# Multiple Identity Configuration (Optional)
|
||
# Define additional identities for the repeater to manage
|
||
# Each identity operates independently with its own key pair and configuration
|
||
identities:
|
||
# Room Server Identities
|
||
# Each room server acts as a separate logical node on the mesh
|
||
room_servers:
|
||
# Example room server configuration (commented out by default)
|
||
# - name: "TestBBS"
|
||
# identity_key: "your_room_identity_key_hex_here"
|
||
# type: "room_server"
|
||
#
|
||
# # Room-specific settings
|
||
# settings:
|
||
# node_name: "Test BBS Room"
|
||
# latitude: 0.0
|
||
# longitude: 0.0
|
||
# admin_password: "room_admin_password"
|
||
# guest_password: "room_guest_password"
|
||
# Add more room servers as needed
|
||
# - name: "SocialHub"
|
||
# identity_key: "another_identity_key_hex_here"
|
||
# type: "room_server"
|
||
# settings:
|
||
# node_name: "Social Hub"
|
||
# latitude: 0.0
|
||
# longitude: 0.0
|
||
# admin_password: "social_admin_123"
|
||
# guest_password: "social_guest_123"
|
||
|
||
# Companion Identities
|
||
# Each companion exposes the MeshCore frame protocol over TCP for standard clients.
|
||
# One TCP client per companion at a time. Clients connect to repeater-ip:tcp_port.
|
||
companions:
|
||
# - name: "RepeaterCompanion"
|
||
# identity_key: "your_companion_identity_key_hex_here"
|
||
# settings:
|
||
# node_name: "RepeaterCompanion"
|
||
# tcp_port: 5000
|
||
# bind_address: "0.0.0.0"
|
||
# tcp_timeout: 120 # seconds; default 120 when omitted; 0 = disable (no timeout)
|
||
# - name: "BotCompanion"
|
||
# identity_key: "another_companion_identity_key_hex"
|
||
# settings:
|
||
# node_name: "meshcore-bot"
|
||
# tcp_port: 5001
|
||
# tcp_timeout: 120 # seconds; default 120 when omitted; 0 = disable (no timeout)
|
||
|
||
# Radio hardware type
|
||
# Supported:
|
||
# - sx1262 (Linux spidev + system GPIO)
|
||
# - sx1262_ch341 (CH341 USB-to-SPI + CH341 GPIO 0-7)
|
||
radio_type: sx1262
|
||
|
||
# CH341 USB-to-SPI adapter settings (only used when radio_type: sx1262_ch341)
|
||
# NOTE: VID/PID are integers. Hex is also accepted in YAML, e.g. 0x1A86.
|
||
ch341:
|
||
vid: 6790 # 0x1A86
|
||
pid: 21778 # 0x5512
|
||
|
||
radio:
|
||
# Frequency in Hz (869.618 MHz for EU)
|
||
frequency: 869618000
|
||
|
||
# TX power in dBm
|
||
tx_power: 14
|
||
|
||
# Bandwidth in Hz (62500 = 62.5 kHz)
|
||
bandwidth: 62500
|
||
|
||
# LoRa spreading factor (7-12)
|
||
spreading_factor: 8
|
||
|
||
# Coding rate (5-8)
|
||
coding_rate: 8
|
||
|
||
# Preamble length in symbols
|
||
preamble_length: 17
|
||
|
||
# Sync word (LoRa network ID)
|
||
sync_word: 13380
|
||
|
||
# Use implicit header mode
|
||
implicit_header: false
|
||
|
||
# KISS modem (when radio_type: kiss). Requires pyMC_core with KISS support.
|
||
# kiss:
|
||
# port: "/dev/ttyUSB0"
|
||
# baud_rate: 9600
|
||
|
||
# SX1262 Hardware Configuration
|
||
# NOTE:
|
||
# - When radio_type: sx1262, these pins are BCM GPIO numbers.
|
||
# - When radio_type: sx1262_ch341, these pins are CH341 GPIO numbers (0-7).
|
||
sx1262:
|
||
# SPI bus and chip select
|
||
# NOTE: For CH341 these are not used but are still required parameters.
|
||
bus_id: 0
|
||
cs_id: 0
|
||
|
||
# GPIO pins
|
||
cs_pin: 21
|
||
reset_pin: 18
|
||
busy_pin: 20
|
||
irq_pin: 16
|
||
|
||
# TX/RX enable pins (-1 to disable)
|
||
txen_pin: -1
|
||
rxen_pin: -1
|
||
|
||
# Optional radio power-enable pin(s) driven HIGH during init
|
||
en_pin: -1
|
||
# en_pins: [26, 23]
|
||
|
||
# LED pins for TX/RX indication (-1 to disable)
|
||
txled_pin: -1
|
||
rxled_pin: -1
|
||
|
||
use_dio3_tcxo: false
|
||
dio3_tcxo_voltage: 1.8
|
||
use_dio2_rf: false
|
||
|
||
# Waveshare hardware flag
|
||
is_waveshare: false
|
||
|
||
delays:
|
||
# TX delay factor for flood mode (multiplier)
|
||
tx_delay_factor: 1.0
|
||
|
||
# TX delay factor for direct mode (faster)
|
||
direct_tx_delay_factor: 0.5
|
||
|
||
duty_cycle:
|
||
# Enable/disable duty cycle enforcement
|
||
# Set to false to disable airtime limits
|
||
enforcement_enabled: false
|
||
|
||
# Maximum airtime per minute in milliseconds
|
||
max_airtime_per_minute: 3600
|
||
|
||
# Storage Configuration
|
||
storage:
|
||
# Directory for persistent storage files (SQLite, RRD).
|
||
# Use a writable path for local/dev (e.g. "./var/pymc_repeater" or "~/var/pymc_repeater").
|
||
storage_dir: "/var/lib/pymc_repeater"
|
||
|
||
# Data retention settings
|
||
retention:
|
||
# Clean up SQLite records older than this many days
|
||
sqlite_cleanup_days: 31
|
||
|
||
# RRD archives are managed automatically:
|
||
# - 1 minute resolution for 1 week
|
||
# - 5 minute resolution for 1 month
|
||
# - 1 hour resolution for 1 year
|
||
|
||
|
||
mqtt_brokers:
|
||
iata_code: "Test" # e.g., "SFO", "LHR", "Test"
|
||
status_interval: 300 # How often a status message is sent (in seconds)
|
||
owner: ""
|
||
email: ""
|
||
brokers: []
|
||
|
||
# Below is the broker object schema:
|
||
# enabled: true|false # Enable this specific mqtt broker
|
||
# name: "" # Internal name for this broker
|
||
# host: "" # hostname or ip of mqtt endpoints
|
||
# port: # Typically 443 for websocket endpoints or 1883 for tcp
|
||
# transport: "tcp" or "websockets"
|
||
# audience: "" # For JWT auth'd endpoints, this is usually the host unless always stated by endpoint owners
|
||
# use_jwt_auth: true|false # Does this endpoint require JWT auth. Mutually Exclusive with Username & Password fields
|
||
# username: "" # Username for basic auth. If empty or missing, uses anonymous access
|
||
# password: "" # Password for basic auth. Required if username is set
|
||
# format: letsmesh|mqtt
|
||
# retain_status: true|false # Sets MQTT "retain" on status messages so they remain on the broker when disconnected. Also enforces a QOS of 1 (guaranteed delivery)
|
||
# tls:
|
||
# enabled: true|false # Enable TLS. If the endpoint's certificate is self-signed, the Root CA should be added to the OS's certificate store.
|
||
# insecure: true|false # Validate TLS certificates
|
||
|
||
# Block specific packet types from being published to the MQTT endpoint
|
||
# If not specified or empty list, all types are published
|
||
# Available types: REQ, RESPONSE, TXT_MSG, ACK, ADVERT, GRP_TXT,
|
||
# GRP_DATA, ANON_REQ, PATH, TRACE, RAW_CUSTOM
|
||
# disallowed_packet_types: []
|
||
# - REQ # Don't publish requests
|
||
# - RESPONSE # Don't publish responses
|
||
# - TXT_MSG # Don't publish text messages
|
||
# - ACK # Don't publish acknowledgments
|
||
# - ADVERT # Don't publish advertisements
|
||
# - GRP_TXT # Don't publish group text messages
|
||
# - GRP_DATA # Don't publish group data
|
||
# - ANON_REQ # Don't publish anonymous requests
|
||
# - PATH # Don't publish path packets
|
||
# - TRACE # Don't publish trace packets
|
||
# - RAW_CUSTOM # Don't publish custom raw packets
|
||
|
||
# Example of using the US and EU LetsMesh endpoints
|
||
# brokers:
|
||
# - name: US West (LetsMesh v1)
|
||
# host: mqtt-us-v1.letsmesh.net
|
||
# port: 443
|
||
# audience: mqtt-us-v1.letsmesh.net
|
||
# use_jwt_auth: true
|
||
# enabled: true
|
||
|
||
# - name: Europe (LetsMesh v1)
|
||
# host: mqtt-eu-v1.letsmesh.net
|
||
# port: 443
|
||
# audience: mqtt-eu-v1.letsmesh.net
|
||
# use_jwt_auth: true
|
||
# enabled: true
|
||
|
||
# pyMC_Glass control-plane integration (optional)
|
||
glass:
|
||
# Enable repeater -> pyMC_Glass /inform loop
|
||
enabled: false
|
||
|
||
# Base URL of Glass backend
|
||
# Example local dev: "http://localhost:8080"
|
||
# Example production: "https://glass.example.com"
|
||
base_url: "http://localhost:8080"
|
||
|
||
# Inform interval in seconds (used as initial/default interval;
|
||
# backend may override via noop.interval response)
|
||
inform_interval_seconds: 30
|
||
|
||
# HTTP timeout per inform request
|
||
request_timeout_seconds: 10
|
||
|
||
# Verify TLS certificates when using HTTPS
|
||
verify_tls: true
|
||
|
||
# Optional bearer token for future authenticated inform endpoints
|
||
api_token: ""
|
||
|
||
# Where cert_renewal payloads are written
|
||
cert_store_dir: "/etc/pymc_repeater/glass"
|
||
|
||
logging:
|
||
# Log level: DEBUG, INFO, WARNING, ERROR
|
||
level: INFO
|
||
|
||
# Log format
|
||
format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||
|
||
# Web interface configuration
|
||
web:
|
||
# Enable Cross-Origin Resource Sharing (CORS) headers
|
||
# Allows web frontends from different origins to access the API
|
||
cors_enabled: false
|
||
|
||
# Custom path to web frontend files (optional)
|
||
# If not specified, uses the default built-in path
|
||
# Example: /opt/custom-web-ui or /home/user/my-frontend
|
||
# web_path: null
|