9.6 KiB
SolarBank IoT Dashboard
A full-stack Docker-based IoT dashboard system for monitoring LILYGO T-A7670G and SIM7000E NB-IoT + GPS modules. This system provides a comprehensive solution for tracking and managing IoT devices, with features for real-time monitoring, data visualization, and device management.
Features
- Real-time Device Monitoring: Track GPS coordinates, signal strength, battery levels, and device status
- LILYGO T-A7670G Support: Native support for LILYGO T-A7670G devices with specialized data endpoints
- Environmental Monitoring: Temperature, humidity, and solar voltage monitoring
- Interactive Map View: Visualize device locations using Leaflet.js with GPS fix status
- Comprehensive Dashboard: View device metrics and system status at a glance
- Device Management: Search, filter, and manage your IoT devices
- Logging System: Track and analyze device logs and events
- REST API: FastAPI backend for device data ingestion and retrieval
- Containerized Architecture: Docker-based deployment for easy setup and scaling
Technology Stack
Frontend
- React.js with WindSurf UI (Tailwind CSS)
- Leaflet.js for map visualization
- Chart.js for data visualization
- Axios for API communication
Backend
- FastAPI (Python) for REST API
- SQLAlchemy ORM for database operations
- PostgreSQL for data storage
- Redis for caching and background tasks
Infrastructure
- Docker and Docker Compose for containerization
- Nginx as reverse proxy with HTTPS support
- Let's Encrypt for SSL certificates
Project Structure
solarbank/
├── backend/ # FastAPI backend application
│ ├── app/ # Application code
│ │ ├── api/ # API endpoints
│ │ ├── core/ # Core functionality
│ │ ├── db/ # Database models and session
│ │ ├── models/ # SQLAlchemy models
│ │ └── services/ # Business logic
│ ├── Dockerfile # Backend Docker configuration
│ ├── requirements.txt # Python dependencies
│ └── migrate_iot_fields.py # Database migration for IoT fields
├── frontend/ # React frontend application
│ ├── public/ # Static files
│ ├── src/ # Source code
│ │ ├── components/ # React components
│ │ ├── pages/ # Page components
│ │ ├── services/ # API services
│ │ └── utils/ # Utility functions
│ ├── Dockerfile # Frontend Docker configuration
│ └── package.json # Node.js dependencies
├── nginx/ # Nginx configuration
│ ├── conf/ # Nginx config files
│ └── Dockerfile # Nginx Docker configuration
├── test_iot_device.py # IoT device testing script
├── .env.example # Example environment variables
└── docker-compose.yml # Docker Compose configuration
Getting Started
Prerequisites
- Docker and Docker Compose
- Git
Installation
-
Clone the repository:
git clone https://github.com/yourusername/solarbank.git cd solarbank -
Create environment files:
cp .env.example .env -
Start the application:
docker-compose up -d -
Access the dashboard:
- Frontend: http://localhost
- API Documentation: http://localhost/api/docs
-
(Optional) Run database migration for existing databases:
cd backend python migrate_iot_fields.py
Environment Variables
The following environment variables can be configured in the .env file:
Backend Settings
API_PREFIX: Prefix for API endpointsDEBUG: Enable debug modePROJECT_NAME: Name of the projectSECRET_KEY: Secret key for securityBACKEND_CORS_ORIGINS: List of allowed CORS origins
Database Settings
POSTGRES_SERVER: PostgreSQL server hostnamePOSTGRES_USER: PostgreSQL usernamePOSTGRES_PASSWORD: PostgreSQL passwordPOSTGRES_DB: PostgreSQL database name
Redis Settings
REDIS_HOST: Redis server hostnameREDIS_PORT: Redis server port
JWT Settings
JWT_SECRET_KEY: Secret key for JWT tokensJWT_ALGORITHM: Algorithm for JWT tokensACCESS_TOKEN_EXPIRE_MINUTES: Token expiration time
Frontend Settings
REACT_APP_API_URL: URL of the backend APIREACT_APP_MAPBOX_TOKEN: Mapbox API token for maps
Nginx Settings
DOMAIN_NAME: Domain name for SSL certificateEMAIL: Email for Let's Encrypt
API Endpoints
Device Endpoints
GET /api/devices: Get all devicesPOST /api/devices: Create a new deviceGET /api/devices/{device_id}: Get a specific devicePUT /api/devices/{device_id}: Update a deviceDELETE /api/devices/{device_id}: Delete a device
Telemetry Endpoints
POST /api/data: Create new telemetry data (standard format)POST /api/data/iot: Create new telemetry data (LILYGO format)GET /api/data/device/{device_id}: Get telemetry for a specific deviceGET /api/data/latest: Get latest telemetry across all devices
Log Endpoints
GET /api/logs: Get all logsPOST /api/logs: Create a new logGET /api/logs/{log_id}: Get a specific logDELETE /api/logs/{log_id}: Delete a log
Status Endpoints
GET /api/status: Get system statusGET /api/status/devices: Get status of all devices
LILYGO T-A7670G Device Integration
Device Data Format
LILYGO T-A7670G devices should send telemetry data to the /api/data/iot endpoint in the following format:
{
"device_id": "LILYGO_001",
"device_name": "Zurich_Station_1",
"firmware": "1.1.0",
"temp": 24.5,
"hum": 65.2,
"solar_volt": 12.8,
"battery_volt": 3.8,
"signal": -65,
"gps_fixed": true,
"latitude": 47.3769,
"longitude": 8.5417,
"altitude": 408.5,
"satellites": 8,
"timestamp": 1234567890
}
Arduino/ESP32 Code Example
// Build JSON payload for LILYGO device
String buildJsonPayload() {
String json = "{";
json += "\"device_id\":\"" + String(DEVICE_ID) + "\",";
json += "\"device_name\":\"" + String(DEVICE_NAME) + "\",";
json += "\"firmware\":\"" + String(FIRMWARE_VERSION) + "\",";
json += "\"temp\":" + String(temperature, 1) + ",";
json += "\"hum\":" + String(humidity, 1) + ",";
json += "\"solar_volt\":" + String(voltageSolar, 2) + ",";
json += "\"battery_volt\":" + String(voltageBattery, 2) + ",";
json += "\"signal\":" + String(signalStrength) + ",";
json += "\"gps_fixed\":" + String(gpsFixed ? "true" : "false") + ",";
json += "\"latitude\":" + String(latitude, 6) + ",";
json += "\"longitude\":" + String(longitude, 6) + ",";
json += "\"altitude\":" + String(altitude, 1) + ",";
json += "\"satellites\":" + String(satellites) + ",";
json += "\"timestamp\":" + String(millis() / 1000);
json += "}";
return json;
}
// Send data to server
bool sendData() {
String json = buildJsonPayload();
String http = "POST /api/data/iot HTTP/1.1\r\n";
http += "Host: " + String(SERVER_IP) + "\r\n";
http += "Content-Type: application/json\r\n";
http += "Content-Length: " + String(json.length()) + "\r\n";
http += "Connection: close\r\n\r\n";
http += json;
// Send via TCP/HTTP
return sendDataViaTCP(http);
}
Field Descriptions
- device_id: Unique device identifier (required)
- device_name: Human-readable device name (optional)
- firmware: Device firmware version (optional)
- temp: Temperature in Celsius (optional)
- hum: Humidity percentage (optional)
- solar_volt: Solar panel voltage (optional)
- battery_volt: Battery voltage - automatically converted to percentage (optional)
- signal: Cellular signal strength in dBm (optional)
- gps_fixed: GPS fix status boolean (optional)
- latitude/longitude: GPS coordinates (optional)
- altitude: Elevation in meters (optional)
- satellites: Number of GPS satellites (optional)
- timestamp: Unix timestamp from device (optional)
Testing IoT Device Integration
Use the provided test script to verify your setup:
python test_iot_device.py
This script simulates LILYGO device data and tests various scenarios including:
- Basic data submission
- Multiple device simulation
- Edge cases (no GPS, low battery)
- Continuous monitoring
Standard Device Data Format (Legacy)
For non-LILYGO devices, use the standard /api/data endpoint with this format:
{
"device_id": "device-001",
"latitude": 47.3769,
"longitude": 8.5417,
"altitude": 408,
"speed": 0,
"heading": 0,
"satellites": 8,
"battery_level": 85,
"signal_strength": -65,
"temperature": 24.5,
"extra_data": {
"humidity": 45,
"pressure": 1013
}
}
Database Migration
For existing installations, run the migration script to add new IoT fields:
cd backend
python migrate_iot_fields.py
This adds the following fields to the telemetry table:
gps_fixed: GPS fix statusbattery_voltage: Raw battery voltagehumidity: Humidity percentagesolar_voltage: Solar panel voltagedevice_timestamp: Device timestamp
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.