Real-time beverage quality monitoring system powered by IoT sensors, InfluxDB time-series storage, and an AI-driven freshness forecast.
An Arduino Nano 33 IoT collects pH, temperature, TDS, and turbidity readings every second, publishes them via MQTT or USB serial, and a Node.js backend fans them out to a browser dashboard over WebSocket. A baseline comparison algorithm classifies the liquid as GOOD / ALERT / BAD and a DeepAI-powered model estimates remaining shelf life in hours.
Arduino Nano 33 IoT (sensors)
│
├─── USB Serial (development, USE_MQTT=false)
└─── MQTT over TLS (production, USE_MQTT=true)
│
▼
Node.js / Express server
├── WebSocket ──────► Browser dashboard (real-time)
├── REST API ──────► /api/history/:field (InfluxDB)
└── /ai-forecast ────► DeepAI API
- Live sensor cards — pH, temperature, TDS, turbidity updated every second
- Real-time visualization — rolling 60-reading line charts per sensor
- Historical charts — 24-hour trend modals backed by InfluxDB
- AI expiration forecast — estimates remaining shelf life via DeepAI, refreshed every 2 hours
- Spoilage status — GOOD / ALERT / BAD derived from baseline deviation on the device
- Dual transport — USB serial for bench testing, MQTT-over-TLS for deployed hardware
- On-device feedback — SSD1306 OLED display + RGB LED status indicators
| Component | Model |
|---|---|
| Microcontroller | Arduino Nano 33 IoT |
| Component | Model / Notes | Arduino Pin |
|---|---|---|
| TDS (total dissolved solids) | Gravity Analog TDS Sensor (DFRobot) | A1 |
| Turbidity | Gravity Analog Turbidity Sensor (DFRobot) | A0 |
| pH | Gravity Analog pH Sensor (DFRobot) | A2 |
| Temperature | DS18B20 one-wire waterproof probe | D2 |
| OLED display | SSD1306 128×64 (I2C, address 0x3C) | SDA/SCL |
| Status LEDs | Green (D3), Yellow (D4), Red (D5) | D3 / D4 / D5 |
| Layer | Technology |
|---|---|
| Firmware | Arduino (WiFiNINA, ArduinoMqttClient, DallasTemperature, Adafruit SSD1306) |
| Backend | Node.js 18+, Express, ws, serialport, mqtt |
| Storage | InfluxDB v2 (@influxdata/influxdb-client) |
| AI (cloud) | DeepAI Chat API via axios |
| AI (local, experimental) | GPT-2 via transformers + torch — see Python utilities |
| Frontend | Vanilla JS, Chart.js, Material Symbols |
| Protocol | WebSocket (live data), REST (historical queries) |
- Node.js ≥ 18
- InfluxDB v2 instance (cloud or self-hosted) with a bucket and API token
- Arduino IDE with the libraries listed in Arduino setup
- DeepAI API key (free tier at deepai.org)
- (Optional) MQTT broker with TLS — e.g. HiveMQ Cloud, Mosquitto
# 1. Clone the repository
git clone https://github.com/your-username/PureMetric.git
cd PureMetric
# 2. Install Node.js dependencies
npm install
# 3. Copy the environment template and fill in your values
cp .env.example .envEdit .env — never commit this file:
# Server
PORT=3000
HOST=localhost
# Transport — set USE_MQTT=false to read from USB serial
USE_MQTT=false
SERIAL_PORT=/dev/tty.usbmodem101 # macOS; use COMx on Windows
SERIAL_BAUD_RATE=115200
# MQTT (required only when USE_MQTT=true)
MQTT_BROKER_URL=mqtts://your-broker.example.com
MQTT_USER=your_mqtt_username
MQTT_PASSWORD=your_mqtt_password
MQTT_TOPIC=iot/liquid/sensor
# InfluxDB
INFLUXDB_URL=https://your-influxdb-instance.example.com
INFLUXDB_TOKEN=your_influxdb_token
INFLUXDB_ORG=your_org
INFLUXDB_BUCKET=your_bucket
# DeepAI
DEEPAI_API_KEY=your_deepai_api_key
AI_FILTER_ENABLED=true- Open
Arduino/LiquidSensor.inoin the Arduino IDE (tested with Arduino IDE 2.x). - Install the following libraries via Tools → Manage Libraries:
WiFiNINAArduinoMqttClientOneWireDallasTemperatureAdafruit GFX LibraryAdafruit SSD1306
- Copy the secrets template and fill in your credentials:
Edit
cp Arduino/arduino_secrets.h.example Arduino/arduino_secrets.h
Arduino/arduino_secrets.h— this file is gitignored and must never be committed:#define SECRET_SSID "your_wifi_ssid" #define SECRET_PASS "your_wifi_password" #define MQTT_BROKER "your-broker.example.com" #define MQTT_PORT 8883 #define MQTT_USERNAME "your_mqtt_username" #define MQTT_PASSWORD "your_mqtt_password"
- Select Tools → Board → Arduino Nano 33 IoT and upload.
The firmware emits a JSON line to Serial every loop iteration:
{"tds":320,"ntu":12.5,"ph":6.87,"temp":22.3,"status":"GOOD"}When USE_MQTT=false, the Node.js server reads this stream directly over USB serial.
# Production
npm start
# Development (auto-restart on changes)
npm run devOpen http://localhost:3000 in your browser.
| Method | Path | Description |
|---|---|---|
GET |
/data |
Last 100 sensor readings (in-memory) |
GET |
/api/history/:field?timeRange=24h |
InfluxDB historical data. field ∈ {ph, temp, tds, ntu} |
GET |
/ai-forecast |
Current AI expiration forecast { success, hours } |
gpt2.py is a standalone experimental script that runs a local GPT-2 model to generate water quality assessments. It is not required by the main application — the production AI path uses the DeepAI API.
# Install dependencies
pip install -r requirements.txt
# Run with a custom prompt (optional)
python gpt2.py "Water quality status:"Requires ~500 MB of disk space for the GPT-2 model weights (downloaded automatically on first run via Hugging Face).
PureMetric/
├── Arduino/
│ ├── LiquidSensor.ino # Firmware (Arduino Nano 33 IoT)
│ ├── arduino_secrets.h # WiFi & MQTT credentials — gitignored, fill locally
│ └── arduino_secrets.h.example # Credentials template (safe to commit)
├── public/
│ ├── index.html # Dashboard UI
│ ├── script.js # Frontend: WebSocket, live charts, tab toggle
│ ├── style.css # Responsive styles
│ └── image/
│ └── water-animation.png
├── server/
│ ├── index.js # Express app & HTTP server
│ ├── config.js # Environment variable loader
│ ├── websocket.js # WebSocket broadcast layer
│ ├── serial.js # USB serial reader
│ ├── mqttClient.js # MQTT subscriber
│ ├── influxdb.js # InfluxDB read/write helpers
│ └── ai-forecast.js # DeepAI API integration
├── gpt2.py # Experimental local GPT-2 script
├── setup.py # Python package definition
├── requirements.txt # Python dependencies (torch, transformers, numpy)
├── .env.example # Environment template (safe to commit)
├── package.json
└── LICENSE
MIT — see LICENSE for details.
