{"id":50108689,"url":"https://github.com/joeyleake/exploration","last_synced_at":"2026-05-23T12:01:36.848Z","repository":{"id":358913848,"uuid":"1240890435","full_name":"joeyleake/expLoRation","owner":"joeyleake","description":"A level editor for the real world.","archived":false,"fork":false,"pushed_at":"2026-05-19T15:01:31.000Z","size":355,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T18:27:34.168Z","etag":null,"topics":["augmented-reality","game-engine","geocaching","gps","lora","meshtastic","meshtastic-python","python","yaml"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joeyleake.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-16T17:41:45.000Z","updated_at":"2026-05-19T15:20:27.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/joeyleake/expLoRation","commit_stats":null,"previous_names":["joeyleake/exploration"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/joeyleake/expLoRation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joeyleake%2FexpLoRation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joeyleake%2FexpLoRation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joeyleake%2FexpLoRation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joeyleake%2FexpLoRation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joeyleake","download_url":"https://codeload.github.com/joeyleake/expLoRation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joeyleake%2FexpLoRation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33394672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["augmented-reality","game-engine","geocaching","gps","lora","meshtastic","meshtastic-python","python","yaml"],"created_at":"2026-05-23T12:01:33.532Z","updated_at":"2026-05-23T12:01:36.843Z","avatar_url":"https://github.com/joeyleake.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" width=\"300\" alt=\"expLoRation\"\u003e\n\u003c/p\u003e\n\n# expLoRation\n\nexpLoRation is a YAML-defined event engine for Meshtastic mesh networks. It listens to GPS position\nupdates and text messages from nodes on the mesh, evaluates configurable trigger conditions, and\nexecutes responses — sending DMs, setting flags, requesting locations, and more. Use it to run\ngeocaching hunts, guided trails, real-world puzzle games, neighborhood monitoring, or any scenario\nwhere physical location and radio messages drive automated behaviour.\n\n---\n\n## Requirements\n\n- Python 3.10 or newer\n- A Meshtastic device reachable via USB serial or TCP\n- Meshtastic firmware 2.x on the device\n\nPython dependencies (installed automatically with pip):\n\n```\nmeshtastic\u003e=2.7.0\nPyYAML\u003e=6.0\npypubsub\u003e=4.0\n```\n\n---\n\n## Installation\n\n```bash\ngit clone https://github.com/joeyleake/expLoRation.git\ncd expLoRation\npip install -r requirements.txt\n```\n\nConnect your Meshtastic device via USB, or have it reachable over TCP, before running.\n\n---\n\n## Quick start\n\nRun the bot against a config file:\n\n```bash\npython bot.py --config game.yaml\n```\n\n**USB serial** — specify the port explicitly or let the bot auto-detect:\n\n```bash\npython bot.py --config game.yaml --port /dev/ttyUSB0\n```\n\n**TCP** — connect to a device running the Meshtastic TCP server (default port 4403):\n\n```bash\npython bot.py --config game.yaml --host 192.168.1.50\npython bot.py --config game.yaml --host 192.168.1.50 --tcp-port 4403\n```\n\nA status summary prints every 5 minutes by default (`--status-interval` to change, `0` to\ndisable).\n\n### Minimal example config\n\nSave this as `quickstart.yaml`, update the coordinates and node ID, and run it to see both core\ntrigger types working:\n\n```yaml\nchannels:\n  - label: main\n    name: LongFast\n    psk: AQ==\n    monitor: true\n    participate: true\n\nzones:\n  - label: start_zone\n    # Replace with a small triangle around your test area\n    points:\n      - [37.7749, -122.4194]\n      - [37.7763, -122.4181]\n      - [37.7751, -122.4168]\n\nmessages:\n  - label: welcome_msg\n    text: \"Welcome! You've entered the zone. Send '!hint' for your first clue.\"\n\n  - label: hint_request\n    text: \"!hint\"\n\n  - label: clue_msg\n    text: \"Clue: head toward the big oak tree.\"\n\nflags:\n  - label: greeted\n\nevents:\n  # Fires when a node enters the zone for the first time\n  - label: greet_on_enter\n    trigger:\n      type: enters_zone\n      target: start_zone\n    responses:\n      - type: send_message\n        message_label: welcome_msg\n        to_triggering_node: true\n      - type: add_flag\n        flag_label: greeted\n        to_triggering_node: true\n    exceptions:\n      - kind: node_has_flag\n        flag: greeted\n\n  # Fires when a node in the zone sends \"!hint\" as a DM\n  - label: hint_command\n    trigger:\n      type: dm\n      message_label: hint_request\n      zone_label: start_zone\n    responses:\n      - type: send_message\n        message_label: clue_msg\n        to_triggering_node: true\n```\n\n```bash\npython bot.py --config quickstart.yaml --verbose\n```\n\nThe `--verbose` flag prints every incoming location update so you can see the bot tracking nodes\nin real time.\n\n---\n\n## Examples\n\nThe [examples/](examples/) directory contains four ready-to-adapt scenarios:\n\n| File | Scenario |\n|---|---|\n| [`geocache.yaml`](examples/geocache.yaml) | Classic geocaching hunt — players enter a start zone, request clues via DM, and race to find a hidden cache |\n| [`ghost_walk.yaml`](examples/ghost_walk.yaml) | Self-guided ghost tour — visitors receive atmospheric story fragments as they approach five points of interest; collecting all five unlocks a final revelation |\n| [`trail_race.yaml`](examples/trail_race.yaml) | Trail race director — automatic checkpoint splits, finish line announcements, cutoff warnings, and sweep alerts for a 5km out-and-back course |\n| [`castle_defense.yaml`](examples/castle_defense.yaml) | Zone-based security monitoring — three escalating alert tiers fire as unknown nodes approach a defended position, with a daily status report |\n| [`augusta_national_rangefinder.yaml`](examples/augusta_national_rangefinder.yaml) | Golf rangefinder — players DM the hole number and receive their distance to that green using live GPS |\n\nAll example files use placeholder coordinates and fictional node IDs. Replace them with your\nactual values before running.\n\n---\n\n## Configuration\n\nAll game logic is defined in a single YAML file. See [CONFIG.md](CONFIG.md) for the complete\nreference covering all trigger types, response types, targets, exceptions, variables, and\nvalidation rules.\n\n---\n\n## Contributing\n\nexpLoRation is an early public release and feedback is very welcome. If you run it in the field,\nfind a bug, have a feature idea, or want to share a config you built, please open an issue or\npull request on GitHub. The goal is to make this useful for the broader Meshtastic community,\nso real-world use reports are especially valuable.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoeyleake%2Fexploration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoeyleake%2Fexploration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoeyleake%2Fexploration/lists"}