Skip to content

Latest commit

 

History

31 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cover

License Build Last commit

Gas Leak Detector - Server

Backend API for the Gas Leak Detector system.
Handles ESP8266 sensor ingestion, persists data to Supabase,
and streams real-time updates to the Android app via WebSocket.

Part of the Gas Leak Detector ecosystem:
ServerESP8266 FirmwareAndroid App


⚠️ This repository contains the server component only.
No hosted instance or pre-built binaries are provided - deployment is your responsibility.

Quick Setup

  1. Deploy to Vercel
  2. Run the Supabase schema
  3. Set environment variables

Project Structure

api/
  historical.js      GET   - paginated historical sensor data
  ingest.js          POST  - primary ESP8266 data ingestion endpoint
  logs.js            GET   - recent logs with pagination
  realtime-config.js GET   - Supabase credentials for Android WebSocket
  stats.js           GET   - hourly aggregated statistics per device
  status.js          GET   - latest reading for a device
lib/
  email.js           Resend email alert helper
  supabase.js        Supabase client, queries, and realtime subscriptions
  validator.js       API key validation, PPM status calculation, input validation
supabase/
  schema.sql         Full database schema - run once in Supabase SQL Editor

API Reference

All endpoints require the header x-api-key: <VALID_API_KEY>.

POST /api/ingest

Primary endpoint for the ESP8266 to push sensor readings. Accepts a single reading or a batch of up to 20.

Single request body:

{ "device_id": "ESP_GASLEAK_01", "ppm": 245 }

Batch request body:

{ "batch": [
  { "device_id": "ESP_GASLEAK_01", "ppm": 245 },
  { "device_id": "ESP_GASLEAK_01", "ppm": 260 }
]}

Response (single):

{ "success": true, "log_id": 1042, "status": "normal" }

Response (batch):

{ "success": true, "count": 2, "results": [{ "id": 1042, "status": "normal" }, ...] }

On each ingested reading, if the status is danger and the cooldown window has passed, an email alert is dispatched via Resend.


GET /api/historical

Returns raw sensor readings for a time range with cursor-based pagination. The Android app calls this on startup to populate the chart.

Query parameters:

Parameter Required Default Description
device_id No - Filter by device. Omit to return all devices.
range No 1d Time window: 1h, 6h, 1d, 7d, 30d
cursor No - Last seen row id for pagination

Response:

{
  "data": [{ "id": 1001, "gas_ppm": 245, "status": "normal", "created_at": "..." }, ...],
  "total": 1000,
  "nextCursor": 2001,
  "range": "1d",
  "device_id": "ESP_GASLEAK_01"
}

Returns up to 1000 rows per page. When nextCursor is null, all data has been returned. The response is gzip-compressed if the client sends Accept-Encoding: gzip.


GET /api/logs

Returns recent readings with descending order and cursor pagination. Intended for debugging and lightweight dashboard queries.

Query parameters:

Parameter Required Default Description
device_id No - Filter by device
limit No 100 Rows per page (max 500)
cursor No - Last seen row id for pagination

Response:

{ "logs": [...], "total": 100, "nextCursor": 940 }

GET /api/status

Returns the most recent reading for a specific device. Useful for a quick health check or polling fallback.

Query parameters:

Parameter Required Description
device_id Yes Target device

Response:

{
  "id": 1042,
  "device_id": "ESP_GASLEAK_01",
  "gas_ppm": 245,
  "status": "normal",
  "ip_address": "192.168.1.5",
  "created_at": "2026-03-15T10:00:00+00:00"
}

GET /api/stats

Returns hourly aggregated statistics from gas_logs_hour. This is the endpoint the Android statistics chart reads from - it never touches raw data, so queries stay fast regardless of data volume.

Query parameters:

Parameter Required Default Description
device_id No - Filter by device. Omit to return all devices.
limit No 10 Number of hourly buckets to return (max 50)

Response:

{
  "data": [
    {
      "bucket": "2026-03-21T10:00:00+00:00",
      "avg_gas": 213.45,
      "min_gas": 180.0,
      "max_gas": 310.0,
      "sample_count": 1800
    }
  ]
}

Results are ordered by bucket descending - most recent hour first.


GET /api/realtime-config

Provides the Supabase URL and anonymous key required for the Android app to establish a direct WebSocket connection to Supabase Realtime. The primary purpose is to allow the Android client to dynamically obtain credentials for subscribing to real-time INSERT events on the gas_logs_raw table, eliminating the need to hardcode sensitive information in the APK.

Response:

{ "url": "https://xxx.supabase.co", "anonKey": "eyJ..." }

The Android app calls this endpoint once at startup, builds the WebSocket URL using the returned credentials, and subscribes to INSERT events on gas_logs_raw to receive live sensor readings.


Supabase Schema

Run supabase/schema.sql once in the Supabase SQL Editor. It creates:

  • devices - registered device registry
  • gas_logs_raw - raw readings from ESP, realtime-enabled
  • gas_logs_minute - per-minute aggregates
  • gas_logs_hour - per-hour aggregates
  • aggregate_gas_minute() and aggregate_gas_hour() - aggregation functions
  • pg_cron jobs for both aggregation functions
  • Row Level Security policies (anon read-only)

Retention Policy

Raw rows in gas_logs_raw are never deleted automatically. Data is preserved based on status:

Status Retention
normal Manual cleanup only - no automatic deletion
warning Kept permanently
danger Kept permanently

Historical queries beyond recent data should use the gas_logs_minute and gas_logs_hour aggregate tables for performance.


Environment Variables

Variable Status Description
SUPABASE_URL Required Your Supabase project URL
SUPABASE_ANON_KEY Required Supabase anonymous key (used by Android WebSocket)
SUPABASE_SERVICE_KEY Required Supabase service role key (used by all server-side writes)
VALID_API_KEY Required Shared secret sent in x-api-key header by ESP and app
RESEND_API_KEY Optional Resend API key for email alerts
ALERT_EMAIL Required Recipient address for danger-level alerts
DANGER_THRESHOLD Required PPM value at or above which status becomes danger (Recommended: 800 for MQ-6)
WARNING_THRESHOLD Required PPM value at or above which status becomes warning (Recommended: 300 for MQ-6)
EMAIL_COOLDOWN_MINUTES Optional Minimum minutes between repeated email alerts (default: 2)

Copy .env to .env.local for local development.


Deploy to Vercel

Vercel is the recommended deployment target. The project deploys as serverless functions with zero configuration.

Option 1: Deploy

Deploy with Vercel

  1. Click the button above
  2. Fill in a repository name and click Create
  3. Add all environment variables in the Vercel dashboard under Settings > Environment Variables
  4. Click Deploy

Option 2: Vercel CLI

  1. Install the Vercel CLI:
npm install -g vercel
  1. Clone and enter the repository:
git clone https://github.com/gasleakdetector/gasleakdetector-server.git
cd gasleakdetector/gasleakdetector-server
  1. Link to Vercel and deploy:
vercel
  1. Add environment variables via the dashboard or CLI:
vercel env add SUPABASE_URL
vercel env add SUPABASE_ANON_KEY
# ... repeat for all variables
  1. Deploy to production:
vercel --prod

Your API will be available at https://<project-name>.vercel.app.


Running Locally

npm install

Create a .env file with the variables listed above, then:

vercel dev

The API is available at http://localhost:3000.


Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Apache 2.0 © Gas Leak Detector


Closing

Have questions or ran into issues? Reach out at pan2512811@gmail.com.
Found this project useful? Consider giving it a ⭐ - it means a lot and helps others discover it. Thanks!

Releases

Packages

Contributors

Languages