Production-ready IoT data acquisition system for TMP117 and BME680 sensors. Collects environmental data via Arduino, stores in SQLite, and sends alerts through Telegram. Includes a real-time web dashboard.
| Feature | Description |
|---|---|
| 🔌 Auto-Reconnect | Resilient serial connection with configurable retry logic |
| 🗄️ SQLite + WAL | Reliable storage with automatic data retention cleanup |
| 📲 Telegram Alerts | Rate-limited notifications with exponential backoff |
| 🏥 Health Checks | Built-in monitoring for serial, database & connectivity |
| 📊 Web Dashboard | Real-time charts, circadian analysis, and calibration insights |
| 🐳 Container Ready | Multi-stage build with Podman Quadlet systemd integration |
# Clone & install
git clone https://github.com/bryamzxz/sensor_app.git && cd sensor_app
pip install -e .
# Configure (copy and edit)
cp .env.example .env
# Run
sensor-appDry-run mode (no Arduino required):
DRY_RUN_MODE=true sensor-appReal-time web dashboard for visualizing sensor data with 6 interactive tabs: Overview, Temperature, Air Quality, Circadian patterns, Calibration analysis, and Insights.
# Install with dashboard dependencies
pip install -e ".[dashboard]"
# Launch dashboard (reads from sensor_app's SQLite database)
sensor-dashboardCLI options:
sensor-dashboard --port 8080 # Custom port
sensor-dashboard --host 0.0.0.0 # Custom bind address
sensor-dashboard --dev # Development mode with hot reloadOpen http://127.0.0.1:5050 in your browser.
The dashboard features:
- Live data via WebSocket — new readings appear automatically
- 7-day hourly averages with temperature, humidity, pressure, and gas resistance charts
- Circadian analysis — day vs night patterns (0-23h breakdown)
- Sensor calibration — TMP117 vs BME680 delta tracking with offset statistics
- Data quality metrics — null counts, total readings, date ranges
| Endpoint | Description |
|---|---|
GET /api/v1/health |
Dashboard health check |
GET /api/v1/stats |
Global statistics (min, max, avg) |
GET /api/v1/hourly |
Hourly averages (default: 168h) |
GET /api/v1/daily |
Daily summary (default: 7 days) |
GET /api/v1/circadian |
Circadian pattern (hour-of-day averages) |
GET /api/v1/calibration |
Sensor delta + offset statistics |
GET /api/v1/quality |
Data quality metrics |
GET /api/v1/latest |
Latest N readings |
WS /ws/live |
Real-time WebSocket stream |
# Terminal 1: Backend API
sensor-dashboard --dev
# Terminal 2: Frontend dev server (hot reload)
cd src/sensor_app/dashboard/frontend
npm install
npm run dev
# Opens http://localhost:5173 (proxied to backend on :5050)To rebuild the frontend for production:
cd src/sensor_app/dashboard/frontend
npm run build # Output → ../static/Essential variables in .env:
TELEGRAM_TOKEN=your_bot_token # Required
TELEGRAM_CHAT_ID=your_chat_id # Required
ARDUINO_VID=0x2341 # Arduino Vendor ID
ARDUINO_PID=0x1002 # Arduino Product ID
DATA_RETENTION_DAYS=7 # Auto-cleanup period
TIMEZONE=America/Bogota # Local timezoneDashboard variables (optional):
DASHBOARD_PORT=5050 # Web server port
DASHBOARD_DATABASE_PATH=data/datos.db
DASHBOARD_POLL_INTERVAL=2.5 # Seconds between DB pollsSee .env.example for all options.
src/sensor_app/
├── config.py # Pydantic settings validation
├── models.py # SensorReading dataclass
├── database.py # Repository pattern (SQLite + WAL)
├── parser.py # Serial data parsing
├── serial_reader.py # Arduino communication
├── telegram_notifier.py # Rate-limited Telegram notifications
├── health.py # Health monitoring
├── logging_config.py # Timezone-aware rotating log setup
└── dashboard/
├── app.py # FastAPI factory + lifespan
├── config.py # DashboardSettings (Pydantic)
├── dependencies.py # FastAPI dependency injection
├── mixins/ # SQL query extensions (aggregation, circadian, calibration, statistics)
├── repositories/ # DashboardRepository (SensorRepository + mixins)
├── routes/ # REST API + WebSocket endpoints
├── services/ # RealtimeService (polling + broadcast)
├── frontend/ # React + Vite source code
└── static/ # Compiled frontend (Vite build output)
# Build (multi-stage: Node.js frontend + Python backend)
sudo podman build -t localhost/sensor-app:latest .
# Run sensor acquisition
sudo podman run -d --name sensor \
--device /dev/ttyACM0 \
-v sensor-data:/app/data \
-v sensor-logs:/app/logs \
--env-file .env \
localhost/sensor-app:latest
# Run dashboard (override CMD)
sudo podman run -d --name dashboard \
-p 5050:5050 \
-v sensor-data:/app/data:ro \
localhost/sensor-app:latest \
sensor-dashboard
# Or with systemd (see docs for Quadlet setup)
sudo systemctl enable --now sensor.servicepip install -e ".[dev,dashboard]" # Install all dev dependencies
pytest --cov # Run tests with coverage (177 tests)
black src/ tests/ # Format code
mypy src/ # Type checking
ruff check src/ tests/ # LintMIT © 2024-2026