A multi-repository solution for tracking LoRaWAN signal range and coverage using LilyGo T-Watch S3, mobile phone GPS, and real-time web services.
LiLoRa combines wearable LoRaWAN hardware, mobile GPS forwarding, and cloud-based visualization to create comprehensive coverage maps for LoRaWAN networks. Perfect for testing gateway range, optimizing network deployment, and validating signal quality in real-world conditions.
- π GPS Tracking: Mobile phone provides GPS coordinates to watch via Bluetooth LE
- π‘ LoRaWAN Integration: SX1262 radio connects to ChirpStack or The Things Network
- πΊοΈ Real-Time Mapping: Live signal quality visualization on mobile app
- π Signal Metrics: Track RSSI, SNR, spreading factor, and packet delivery
- πΎ Session Recording: Save and export range tests as GeoJSON/KML
- π Low Power: Optimized for extended field testing (940mAh battery)
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Mobile Phone β β T-Watch S3 β β LoRaWAN β
β (GPS Source) βββββBLEβββ€ (ESP32-S3 + ββββLoRaβββΊβ Gateway β
β β β SX1262 Radio) β β β
βββββββββββββββββββ ββββββββββββββββββββ ββββββββββ¬βββββββββ
β β
β β
β ββββββββββββββββββββ β
βββββββWebSocketβββββ€ FastAPI Backend ββββββWebhookββββββ
β (Real-time Srv) β
ββββββββββ¬ββββββββββ
β
ββββββββββΌββββββββββ
β ChirpStack or β
β The Things Net β
ββββββββββββββββββββ
This project is organized as a multi-repository setup:
lilora/ # This repository (documentation & planning)
β
βββ README.md # Project overview (this file)
βββ CLAUDE.md # Development guide for Claude Code
βββ PROJECT_PLAN.md # Detailed phase-by-phase implementation plan
β
βββ lilora-firmware/ # T-Watch S3 firmware (create separately)
β βββ platformio.ini # PlatformIO configuration
β βββ src/
β β βββ main.cpp # Main firmware loop
β β βββ lorawan_config.h # LoRaWAN credentials (gitignored)
β β βββ bluetooth.cpp # BLE NMEA server
β β βββ nmea_parser.cpp # GPS data parser
β β βββ payload_encoder.cpp # Binary encoding
β βββ lib/ # LilyGoLib, RadioLib
β
βββ lilora-mobile/ # Flutter mobile app (create separately)
β βββ pubspec.yaml # Flutter dependencies
β βββ lib/
β β βββ main.dart # App entry point
β β βββ screens/
β β β βββ home_screen.dart
β β β βββ map_screen.dart
β β βββ services/
β β β βββ bluetooth_service.dart
β β β βββ gps_service.dart
β β β βββ websocket_service.dart
β β βββ models/
β β βββ range_point.dart
β βββ android/ & ios/ # Platform-specific config
β
βββ lilora-backend/ # FastAPI backend (create separately)
βββ main.py # FastAPI app
βββ requirements.txt # Python dependencies
βββ models/
β βββ uplink.py # ChirpStack/TTN schemas
βββ services/
β βββ decoder.py # Payload decoder
β βββ websocket_manager.py # Connection manager
βββ Dockerfile # Container deployment
-
Hardware:
- LilyGo T-Watch S3 (with SX1262 LoRa radio, 868MHz or 915MHz)
- Android or iOS smartphone with GPS
- LoRaWAN gateway (or access to public TTN coverage)
-
Software:
- PlatformIO CLI (firmware development)
- Flutter SDK 3.x (mobile app)
- Python 3.10+ (backend service)
- ChirpStack or TTN account
-
Register LoRaWAN Device:
- Create account on ChirpStack or The Things Network
- Register new device with OTAA activation
- Note DevEUI, AppEUI (JoinEUI), AppKey
-
Flash Firmware:
cd lilora-firmware # Edit src/lorawan_config.h with your keys pio run --target upload
-
Configure Backend:
cd lilora-backend # Using uv (recommended) uv sync uv run uvicorn main:app --host 0.0.0.0 --port 8000 # Or using pip pip install -r requirements.txt uvicorn main:app --host 0.0.0.0 --port 8000 # Add webhook integration in ChirpStack/TTN console
-
Run Mobile App:
cd lilora-mobile flutter pub get flutter run -
Start Range Test:
- Open mobile app, connect to T-Watch via Bluetooth
- Enable GPS forwarding
- Walk away from gateway while watching signal quality
- View real-time coverage map
Development is structured in 5 phases (see PROJECT_PLAN.md for details):
- LoRaWAN OTAA join to ChirpStack/TTN
- Session persistence (NVS storage)
- Uplink/downlink tested and working
- BLE Serial Server on T-Watch (Nordic UART Service)
- NMEA sentence generation in Flutter app
- GPS data encoding in LoRaWAN payload (13-byte binary format)
- FastAPI webhook receiver (ChirpStack & TTN)
- WebSocket broadcast manager for real-time updates
- Payload decoder with Haversine distance calculation
- 19/19 tests passing
- Map integration with range plotting
- Live signal metrics dashboard
- Session recording and export
- Adaptive Data Rate monitoring
- Multi-gateway support
- Offline mode with sync
| Component | Technology | Purpose |
|---|---|---|
| Firmware | PlatformIO + Arduino | ESP32-S3 development |
| RadioLib 6.6.0 | LoRaWAN stack (SX1262) | |
| ESP32 BLE | Bluetooth LE server | |
| Mobile | Flutter 3.x | Cross-platform UI |
| flutter_blue_plus | Bluetooth LE client | |
| geolocator | GPS access | |
| Backend | FastAPI + uv | Async web framework |
| WebSockets | Real-time updates | |
| Pydantic | Data validation | |
| Network | ChirpStack or TTN | LoRaWAN network server |
- Network Planning: Map coverage before deploying IoT devices
- Gateway Optimization: Test antenna placement and configuration
- Interference Analysis: Identify signal dead zones and obstacles
- Regulatory Compliance: Verify duty cycle and power limits
- Community Mapping: Contribute to public LoRaWAN coverage databases
LilyGo T-Watch S3:
- ESP32-S3 dual-core @ 240MHz (16MB Flash, 8MB PSRAM)
- SX1262 LoRa transceiver (433/868/915MHz)
- Bluetooth 5.0 Low Energy
- 1.54" LCD touchscreen (240x240)
- BMA423 accelerometer
- 940mAh battery (USB-C charging)
No GPS on watch: GPS coordinates provided by mobile phone via Bluetooth LE using NMEA protocol.
This project is in active development. Contributions welcome!
- Fork the relevant repository (firmware, mobile, or backend)
- Create feature branch:
git checkout -b feature/my-feature - Commit changes:
git commit -am 'Add new feature' - Push to branch:
git push origin feature/my-feature - Open Pull Request
LoRaWAN Join Fails:
- Verify OTAA keys match network server exactly
- Enable "Resets DevNonces" in device settings (development only)
- Check gateway is online and in range
BLE Connection Drops:
- Ensure location permissions granted on mobile app
- Keep phone within 10m of watch
- Disable battery optimization for app
Backend Not Receiving Data:
- Confirm webhook URL is publicly accessible
- Check network server integration logs
- Test with curl:
curl -X POST https://your-backend/webhook/chirpstack -d @sample.json
See CLAUDE.md for detailed troubleshooting guide.
- CLAUDE.md - Comprehensive development guide for Claude Code
- LilyGo T-Watch S3 Wiki
- ChirpStack Documentation
- The Things Network Docs
This project is released under MIT License. Individual components (LilyGoLib, RadioLib, Flutter, FastAPI) retain their original licenses.
- LilyGo - T-Watch S3 hardware platform
- Jan GromeΕ‘ - RadioLib LoRaWAN implementation
- ChirpStack/TTN - Open-source network server infrastructure
- Flutter & FastAPI communities - Excellent frameworks and documentation
Project Status: Phases 1-3 Complete - Firmware, mobile BLE app, and backend service all working. Ready for Phase 4 (Mobile Visualization).
Maintainer: Boris Gomiunik Created: January 2026 Last Updated: January 2026