[Connection] # Connection type: serial, ble, or tcp # serial: Connect via USB serial port # ble: Connect via Bluetooth Low Energy # tcp: Connect via TCP/IP connection_type = serial # Serial port (for serial connection) # Common ports: /dev/ttyUSB0, /dev/tty.usbserial-*, COM3 (Windows) serial_port = /dev/ttyUSB0 # BLE device name (for BLE connection) # Leave commented out for auto-detection, or specify exact device name #ble_device_name = MeshCore # TCP hostname or IP address (for TCP connection) #hostname = 192.168.1.60 # TCP port (for TCP connection) #tcp_port = 5000 # Connection timeout in seconds timeout = 30 [Bot] # Bot name for identification and logging bot_name = MeshCoreBot # RF Data Correlation Settings # Time window for correlating RF data with messages (seconds) rf_data_timeout = 15.0 # Time to wait for RF data correlation (seconds) message_correlation_timeout = 10.0 # Enable enhanced correlation strategies enable_enhanced_correlation = true # Bot node ID (leave empty for auto-assignment) node_id = # Enable/disable bot responses # true: Bot will respond to keywords and commands # false: Bot will only listen and log messages enabled = true # Passive mode (only listen, don't respond) # true: Bot will not send any messages # false: Bot will respond normally passive_mode = false # Rate limiting in seconds between messages # Prevents spam by limiting how often the bot can send messages rate_limit_seconds = 10 # Bot transmission rate limit in seconds between bot messages # Prevents bot from overwhelming the mesh network bot_tx_rate_limit_seconds = 1.0 # Transmission delay in milliseconds before sending messages # Helps prevent message collisions on the mesh network # Recommended: 100-500ms for busy networks, 0 for quiet networks tx_delay_ms = 250 # DM retry settings for improved reliability (meshcore-2.1.6+) # Maximum number of retry attempts for failed DM sends dm_max_retries = 3 # Maximum flood attempts (when path reset is needed) dm_max_flood_attempts = 2 # Number of attempts before switching to flood mode dm_flood_after = 2 # Timezone for bot operations # Use standard timezone names (e.g., "America/New_York", "Europe/London", "UTC") # Leave empty to use system timezone timezone = # Bot location for geographic proximity calculations and astronomical data # Default latitude for bot location (decimal degrees) # Example: 40.7128 for New York City, 48.50 for Victoria BC bot_latitude = 40.7128 # Default longitude for bot location (decimal degrees) # Example: -74.0060 for New York City, -123.00 for Victoria BC bot_longitude = -74.0060 [Localization] # Language code for bot responses (en, es, es-MX, es-ES, fr, de, ja, etc.) # Default: en (English) # The bot will use translations from translations/{language}.json # Supports locale codes: # - Simple codes: en, es, fr, de, ja # - Locale codes: es-MX (Mexican Spanish), es-ES (Spain Spanish), fr-CA (Canadian French) # If locale-specific file not found, falls back to base language (e.g., es.json) # If translation file is missing or key not found, falls back to English language = en # Path to translation files directory (relative to bot root) # Default: translations/ translation_path = translations/ [Admin_ACL] # Admin Access Control List (ACL) for restricted commands # Only users with public keys listed here can execute admin commands # Format: comma-separated list of public keys (without spaces) # Example: 3e14a5fa9c52e7b6b8e14f987cd12ab1e3dc9fb64a2bbf0e19dca85e9f43a120, another key here admin_pubkeys = # Commands that require admin access (comma-separated) # These commands will only work for users in the admin_pubkeys list admin_commands = repeater,webviewer [Plugin_Overrides] # Plugin Overrides - Use alternative plugin implementations # Format: command_name = alternative_file_name # The alternative_file_name should be the name of a Python file (without .py extension) # in the modules/commands/alternatives/ directory # # Example: To use an alternative weather plugin for international users: # wx = wx_international # # This will replace the default wx command with the plugin from # modules/commands/alternatives/wx_international.py # # Note: The alternative plugin must have the same 'name' metadata as the command # it's replacing, or the override will use the alternative plugin's name instead. [Companion_Purge] # Enable companion contact purging # true: Purge inactive companions when contact list is full # false: Never purge companions (default: false for safety) companion_purge_enabled = false # Days since last DM to consider companion inactive # Companions who haven't DM'd the bot in this many days may be purged companion_dm_threshold_days = 30 # Days since last advert to consider companion inactive # Companions who haven't adverted in this many days may be purged companion_advert_threshold_days = 30 # Minimum days since last activity (DM or advert) before purge # Companions must be inactive for at least this many days companion_min_inactive_days = 30 [Jokes] # Enable or disable the joke command # true: Joke command is available # false: Joke command is disabled joke_enabled = true # Enable seasonal joke defaults # When enabled, October defaults to spooky jokes, December defaults to Christmas jokes # true: Seasonal defaults are applied # false: No seasonal defaults (always random) seasonal_jokes = true # Enable or disable the dad joke command # true: Dad joke command is available # false: Dad joke command is disabled dadjoke_enabled = true # Handle long jokes (over 130 characters) # false: Fetch new jokes until we get a short one # true: Split long jokes into multiple messages long_jokes = false # Send startup advert when bot finishes initializing # false: No startup advert (default) # zero-hop: Send local broadcast advert # flood: Send network-wide flood advert startup_advert = false # Auto-manage contact list when new contacts are discovered # device: Device handles auto-addition using standard auto-discovery mode, bot manages contact list capacity (purge old contacts when near limits) # bot: Bot automatically adds new companion contacts to device, bot manages contact list capacity (purge old contacts when near limits) # false: Manual mode - no automatic actions, use !repeater commands to manage contacts (default) auto_manage_contacts = false # Interval-based advertising settings # Send periodic flood adverts at specified intervals # 0: Disabled (default) # >0: Send flood advert every N hours advert_interval_hours = 0 [Keywords] # Keyword-response pairs (keyword = response format) # Available fields: {sender}, {connection_info}, {snr}, {timestamp}, {path}, {path_distance}, {firstlast_distance} # {sender}: Name/ID of message sender # {connection_info}: "Direct connection (0 hops)" or "Routed through X hops" # {snr}: Signal-to-noise ratio in dB # {timestamp}: Message timestamp in HH:MM:SS format # {path}: Message routing path (e.g., "01,5f (2 hops)") # {rssi}: Received Signal Strength Indicator in dBm # {path_distance}: Total distance between all hops in path with locations (e.g., "123.4km (3 segs, 1 no-loc)") # {firstlast_distance}: Distance between first and last repeater in path (e.g., "45.6km" or empty if locations missing) test = "ack @[{sender}]{phrase_part} | {connection_info} | Received at: {timestamp}" ping = "Pong!" pong = "Ping!" help = "Bot Help: test (or t), ping, help, hello, cmd, advert, @string, wx, aqi, sun, moon, solar, hfcond, satpass, prefix, path, sports, dice, roll, stats | Use 'help ' for details" cmd = "Available commands: test (or t), ping, help, hello, cmd, advert, @string, wx, aqi, sun, moon, solar, hfcond, satpass, prefix, path, sports, dice, roll, stats" [Channels] # Channels to monitor (comma-separated) # Bot will only respond to messages on these channels # Use exact channel names as configured on your MeshCore node monitor_channels = general,test,emergency # Enable DM responses # true: Bot will respond to direct messages # false: Bot will ignore direct messages respond_to_dms = true [Banned_Users] # List of banned user IDs (comma-separated) # Bot will ignore messages from these users banned_users = [Scheduled_Messages] # Scheduled message format: HHMM = channel:message # Time format: HHMM (24-hour, no colon) # Bot will send these messages at the specified times daily # Example: 0800 = general:Good morning! Weather update coming soon. 0800 = general:Good morning! Bot is online and ready. 1200 = general:Midday status check - all systems operational. 1800 = general:Evening update - bot status: Good [Logging] # Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL # DEBUG: Most verbose, shows all details # INFO: Standard logging level # WARNING: Only warnings and errors # ERROR: Only errors # CRITICAL: Only critical errors log_level = INFO # Log file path (leave empty for console only) # Bot will write logs to this file in addition to console log_file = meshcore_bot.log # Enable colored console output # true: Use colors in console output # false: Plain text output colored_output = true # MeshCore library log level (separate from bot log level) # Controls debug output from the meshcore library itself # Options: DEBUG, INFO, WARNING, ERROR, CRITICAL meshcore_log_level = INFO [Greeter_Command] # Enable or disable the greeter command # true: Bot will greet users on their first public channel message # false: Greeter is disabled enabled = false # Channels where greetings should occur (comma-separated) # If not specified, uses the channels from [Channels] monitor_channels setting # Example: general,welcome,newbies # Leave empty to use monitor_channels from [Channels] section channels = # Greeting message template (default for all channels) # Available fields: {sender} - the user's name/ID # For multi-part greetings, separate messages with pipe (|) # Example (single): "Welcome to the mesh, @[{sender}]!" # Example (multi-part): "Welcome to the mesh, @[{sender}]!|This is a great place to chat.|Use !help for commands." greeting_message = Welcome to the mesh, @[{sender}]! # Channel-specific greeting messages (optional) # Format: channel_name:greeting_message,channel_name2:greeting_message2 # If a channel has a specific greeting, it will be used instead of the default greeting_message # Example: Public:Welcome to Public channel, @[{sender}]!|general:Welcome to general, @[{sender}]! # Multi-part greetings are supported per channel using pipe (|) separator # Leave empty to use greeting_message for all channels channel_greetings = # Per-channel greetings (tracking behavior) # false: Greet each user only once globally (default - user gets one greeting total) # true: Greet each user once per channel (user can be greeted on each channel separately) # Note: This controls tracking, not the greeting message itself. Use channel_greetings for different messages. per_channel_greetings = false # Include mesh network information in greeting # true: Add mesh statistics to greeting (total contacts, repeaters, etc.) # false: Only send the greeting message include_mesh_info = true # Mesh info format template # Available fields: {total_contacts}, {repeaters}, {companions}, {recent_activity_24h} # Example: "\n\nMesh Info: {total_contacts} contacts, {repeaters} repeaters" # Note: Mesh info is appended to the last greeting message part mesh_info_format = \n\nMesh Info: {total_contacts} contacts, {repeaters} repeaters, {recent_activity_24h} active in last 24h # Rollout period in days # When greeter is first enabled on an active mesh, this sets how many days # to listen and mark all active users as already greeted before beginning # to greet new users. This prevents greeting everyone on an established mesh. # Set to 0 to disable rollout (will greet all new users immediately) # Note: Use auto_backfill to mark historical users and shorten/eliminate rollout period rollout_days = 7 # Auto-backfill from historical message_stats data # true: Automatically mark all users who have posted on public channels in the past # false: Only mark users during rollout period (default) # This allows shortening or eliminating the rollout period by using existing data auto_backfill = false # Backfill lookback period in days # Number of days to look back when auto-backfilling (0 = all time) # Only used if auto_backfill = true # Example: 30 = only mark users who posted in last 30 days # Example: 0 = mark all users who have ever posted (all time) backfill_lookback_days = 30 [Custom_Syntax] # Custom syntax patterns for special message formats # Format: pattern = "response_format" # Available fields: {sender}, {phrase}, {connection_info}, {snr}, {timestamp}, {path}, {path_distance}, {firstlast_distance} # {phrase}: The text after the trigger (for custom syntax patterns) # {path_distance}: Total distance between all hops in path with locations (e.g., "123.4km (3 segs, 1 no-loc)") # {firstlast_distance}: Distance between first and last repeater in path (e.g., "45.6km" or empty if locations missing) # # Note: The "t" command is now handled by the test command as an alias # "t phrase" works the same as "test phrase" - both use the test response format # Example: "t hello world" -> "ack {sender}: hello world | {connection_info}" [External_Data] # Weather API key (future feature) weather_api_key = # Weather update interval in seconds (future feature) weather_update_interval = 3600 # Tide API key (future feature) tide_api_key = # Tide update interval in seconds (future feature) tide_update_interval = 1800 # N2YO API key for satellite pass information # Get free key at: https://www.n2yo.com/login/ n2yo_api_key = # AirNow API key for AQI data # Get free key at: https://docs.airnowapi.org/ airnow_api_key = # Forecast.Solar API key for solar forecast data # Get key at: https://forecast.solar/ (free tier works without key, paid tier for 3+ day forecasts) # Free tier: 2-day forecast, 1-hour resolution # Paid tier (14 EUR/year): 3-6 day forecast, 15-30 minute resolution forecast_solar_api_key = # Repeater prefix API URL for prefix command # Leave empty to disable prefix command functionality # Example: https://map.w0z.is/api/stats/repeater-prefixes?region=seattle # Note: w0z.is is regionally available - configure your own regional API repeater_prefix_api_url = # Repeater prefix cache duration in hours # How long to cache prefix data before refreshing from API # Recommended: 1-6 hours (data doesn't change frequently) repeater_prefix_cache_hours = 1 [Prefix_Command] # Enable or disable repeater geolocation in prefix command # true: Show city names with repeaters when location data is available # false: Show only repeater names without location information show_repeater_locations = true # Use reverse geocoding for coordinates without city names # true: Automatically look up city names from GPS coordinates # false: Only show coordinates if no city name is available use_reverse_geocoding = true # Hide prefix source information # true: Hide "Source: domain.com" line from prefix command output # false: Show source information (default) hide_source = false # Prefix heard time window (days) # Number of days to look back when showing prefix results (default command behavior) # Only repeaters heard within this window will be shown by default # Use "prefix XX all" to show all repeaters regardless of time prefix_heard_days = 7 # Prefix free time window (days) # Number of days to look back when determining which prefixes are "free" # Only repeaters heard within this window will be considered as using a prefix # Repeaters not heard in this window will be excluded from used prefixes list prefix_free_days = 30 # Maximum range for prefix filtering (kilometers) # Repeaters beyond this distance from bot location will be excluded from prefix lookups # This prevents prefix collisions from far-away repeaters from affecting local prefix availability # Set to 0 to disable range limiting max_prefix_range = 200 [Weather] # Default state for city name disambiguation # When users type "wx seattle", it will search for "seattle, WA, USA" # Use 2-letter state abbreviation (e.g., WA, CA, NY, TX) default_state = WA # Default country for city name disambiguation (for international weather plugin) # Use 2-letter country code (e.g., US, CA, GB, AU) default_country = US # Temperature unit for weather display # Options: fahrenheit, celsius # Default: fahrenheit temperature_unit = fahrenheit # Wind speed unit for weather display # Options: mph, kmh, ms (meters per second) # Default: mph wind_speed_unit = mph # Precipitation unit for weather display # Options: inch, mm # Default: inch precipitation_unit = inch [Solar_Config] # URL timeout for external API calls (seconds) url_timeout = 10 # Use Zulu/UTC time for astronomical data # true: Use 24-hour UTC format # false: Use 12-hour local format use_zulu_time = false [Channels_List] # Common hashtag channels for the region # Format: channel_name = description # These channels will be listed when users use the 'channels' command # The bot will automatically add the '#' prefix when displaying channels # General channels (no category prefix) general = General discussion and chat weather = Weather updates and conditions emergency = Emergency communications and alerts # Sub-command channels (format: subcommand.channel_name = description) # Example: channels sports -> sports.sounders = Seattle Sounders FC # Sports-focused channels sports.sounders = Seattle Sounders FC sports.kraken = Seattle Kraken sports.mariners = Seattle Mariners sports.seahawks = Seattle Seahawks sports.reign = OL Reign sports.storm = Seattle Storm sports.huskies = Washington Huskies # Local area channels local.capitolhill = Capitol Hill neighborhood local.ballard = Ballard neighborhood local.fremont = Fremont neighborhood local.queenanne = Queen Anne neighborhood # Technology channels tech.mesh = Mesh networking and technical discussions tech.hamradio = Amateur radio and ham radio topics tech.programming = Programming and development tech.iot = Internet of Things projects # Emergency-focused channels emergency.emergency = Emergency communications and alerts emergency.weather = Weather updates and conditions emergency.traffic = Traffic updates and road conditions emergency.hamradio = Amateur radio emergency net [Sports_Command] # Enable or disable the sports command # true: Sports command is available # false: Sports command is disabled sports_enabled = true # Default teams to show when 'sports' command is used without arguments # Comma-separated list of team names (use lowercase) teams = seahawks,mariners,sounders,kraken # Channels where sports command is allowed (leave empty for all channels) # Comma-separated list of channel names channels = general,#bot,#sounders,#seahawks # Channel overrides for sports command # Format: channel_name = default_team # Allows sports command to work in specific channels with default team shortcuts # Example: #sounders = sounders (sports in #sounders becomes "sports sounders") channel_override = #sounders=sounders,#seahawks=seahawks,#kraken=kraken,#mariners=mariners # ESPN API timeout in seconds api_timeout = 10 [Stats_Command] # Enable or disable the stats command # true: Stats command is available # false: Stats command is disabled stats_enabled = true # Data retention settings # Number of days to keep stats data (older data will be automatically cleaned up) # Recommended: 7-30 days to balance storage usage with historical data data_retention_days = 7 # Enable automatic cleanup of old stats data # true: Automatically clean up old data based on data_retention_days # false: Manual cleanup only auto_cleanup = true # Stats collection settings # Track all incoming messages (not just commands) # true: Record all messages for comprehensive stats # false: Only record command executions track_all_messages = true # Track command execution details # true: Record detailed command execution info # false: Basic command tracking only track_command_details = true # Privacy settings # Anonymize user data in stats # true: Replace user IDs with anonymous identifiers # false: Keep actual user IDs in stats anonymize_users = false [Path_Command] # Geographic proximity calculation method # simple: Use proximity to bot location (default) # path: Use proximity to previous/next nodes in the path for more realistic routing proximity_method = simple # Enable path proximity fallback # When path proximity can't be calculated (missing location data), fall back to simple proximity # true: Fall back to bot location proximity when path data unavailable # false: Show collision warning when path proximity unavailable path_proximity_fallback = true # Maximum range for geographic proximity guessing (kilometers) # Repeaters beyond this distance will have reduced confidence or be rejected # Set to 0 to disable range limiting max_proximity_range = 200 # Maximum age for repeater data in path matching (days) # Only include repeaters that have been heard within this many days # Helps filter out stale or inactive repeaters from path decoding # Set to 0 to disable age filtering max_repeater_age_days = 14 # Star bias multiplier for path command # When a contact is starred in the web viewer, multiply its selection score by this value # Higher values = stronger preference for starred repeaters # Default: 2.5 (starred repeaters get 2.5x their normal score) # Set to 1.0 to disable star bias star_bias_multiplier = 2.5 # Recency vs Proximity weighting (0.0 to 1.0) # Controls how much recency (when last heard) vs proximity (distance) matters # 0.0 = 100% proximity (only distance matters) # 1.0 = 100% recency (only when last heard matters) # 0.4 = 40% recency, 60% proximity (default - balanced for path routing) # Lower values favor closer repeaters, higher values favor recently heard repeaters recency_weight = 0.4 # Confidence indicator symbols for path command # High confidence (>= 0.9): Shows when path decoding is very reliable high_confidence_symbol = 🎯 # Medium confidence (>= 0.8): Shows when path decoding is reasonably reliable medium_confidence_symbol = 📍 # Low confidence (< 0.8): Shows when path decoding has uncertainty low_confidence_symbol = ❓ # Enable "p" shortcut for path command (similar to "t" for test command) # true: Respond to just "p" or "p " as a shortcut for "path" # false: Only respond to "path", "decode", or "route" keywords (default) enable_p_shortcut = false [Hacker_Command] # Enable or disable the hacker command # true: Hacker command is available (responds to Linux commands with supervillain mainframe errors) # false: Hacker command is disabled hacker_enabled = false [Web_Viewer] # Enable or disable the web data viewer # true: web viewer is available for viewing bot data # false: web viewer is disabled enabled = true # Web viewer host address # 127.0.0.1: Only accessible from localhost # 0.0.0.0: Accessible from any network interface host = 127.0.0.1 # Web viewer port # Default: 8080 (viewer uses port 8080) port = 8080 # Enable debug mode for the web viewer # true: Enable Flask debug mode (auto-reload on changes) # false: Production mode debug = false # Auto-start web viewer with bot # true: Start web viewer automatically when bot starts # false: Start web viewer manually auto_start = false