# 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 # Duplicate packet cache TTL in seconds cache_ttl: 3600 # 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 # Mesh Network Configuration mesh: # Global flood policy - controls whether the repeater allows or denies flooding by default # true = allow flooding globally, false = deny flooding globally # Individual transport keys can override this setting global_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 # 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 # MQTT Publishing Configuration (Optional) mqtt: # Enable/disable MQTT publishing enabled: false # MQTT broker settings broker: "localhost" port: 1883 # Use 8883 for TLS/SSL, 80/443/9001 for WebSockets # Use WebSocket transport instead of standard TCP # Typically uses ports: 80 (ws://), 443 (wss://), or 9001 use_websockets: false # Authentication (optional) username: null password: null # TLS/SSL configuration (optional) # For public brokers with trusted certificates, just enable TLS: # tls: # enabled: true tls: enabled: false # Advanced TLS options (usually not needed for public brokers): # Custom CA certificate for server verification # Leave null to use system default CA certificates (recommended) ca_cert: null # e.g., "/etc/ssl/certs/ca-certificates.crt" # Client certificate and key for mutual TLS (rarely needed) client_cert: null # e.g., "/etc/pymc/client.crt" client_key: null # e.g., "/etc/pymc/client.key" # Skip certificate verification (insecure, not recommended) insecure: false # Base topic for publishing # Messages will be published to: {base_topic}/{node_name}/{packet|advert} base_topic: "meshcore/repeater" # 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 letsmesh: enabled: false iata_code: "Test" # e.g., "SFO", "LHR", "Test" # ============================================================ # BROKER SELECTION MODE - Choose how to connect to brokers # ============================================================ # # EXAMPLE 1: Single built-in broker (default, most common) # Connect to Europe only - simple, low bandwidth broker_index: 0 # 0 = Europe, 1 = US West # EXAMPLE 2: All built-in brokers for maximum redundancy # Survives single broker failure, best uptime # broker_index: -1 # or null - connects to both EU and US # EXAMPLE 3: Only custom brokers (private/self-hosted) # Ignores built-in LetsMesh brokers completely # broker_index: -2 # additional_brokers: # - name: "Private Server" # host: "mqtt.myserver.com" # port: 443 # audience: "mqtt.myserver.com" # EXAMPLE 4: Single built-in + custom backup # Use EU primary with your own backup # broker_index: 0 # additional_brokers: # - name: "Backup Server" # host: "mqtt-backup.mydomain.com" # port: 8883 # audience: "mqtt-backup.mydomain.com" # EXAMPLE 5: All built-in + multiple custom (maximum redundancy) # EU + US + your own servers - best for critical deployments # broker_index: -1 # additional_brokers: # - name: "Custom Primary" # host: "mqtt-1.mydomain.com" # port: 443 # audience: "mqtt-1.mydomain.com" # - name: "Custom Backup" # host: "mqtt-2.mydomain.com" # port: 443 # audience: "mqtt-2.mydomain.com" # ============================================================ status_interval: 300 owner: "" email: "" # Block specific packet types from being published to LetsMesh # 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 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