Real-Time Hardware Fault Detection Platform by Junaid ShahReal-Time Hardware Fault Detection Platform by Junaid Shah

Real-Time Hardware Fault Detection Platform

Junaid Shah

Junaid Shah

Real-Time Hardware Fault Detection Platform

An end-to-end system that ingests raw sensor + log telemetry, cleans and labels it, trains an interpretable fault-detection model, and surfaces live predictions through a monitoring dashboard with alerting.

1. Architecture & design choices

Data layer (data/data_pipeline.py) Sensor telemetry (temperature, voltage, vibration) and system log events (severity, message) are ingested, cleaned (per-sensor median imputation, physically-plausible range clipping, deduplication), and merged: each sensor reading gets a recent_log_severity_score — a decayed sum of nearby WARNING/ERROR/CRITICAL log weights — so the model can use log bursts as a leading indicator, not just instantaneous readings. The result is persisted to a local SQLite table (data_store/telemetry.db) that acts as a lightweight feature store; swap the mock generators for real Kafka/S3/DB connectors and the rest of the pipeline is unaffected.
Labeling rule (matches your business definition): label = 1 (Fault) if temperature > 85°C AND voltage > 240V, else 0.
Model layer (model/model.py) A Random Forest classifier was chosen deliberately over a deep learning approach:
Native, per-feature importance scores — engineers can see why an alert fired, which matters more here than squeezing out marginal accuracy.
Sub-millisecond CPU inference, no GPU dependency — fits a "real-time" dashboard with modest tabular features.
Robust to a small, mixed-scale feature set without heavy tuning.
If you outgrow this (e.g. much larger feature sets, sequential/ time-series patterns across a sliding window), a gradient-boosted tree (XGBoost/LightGBM) is the natural next step before reaching for a neural network — TensorFlow/PyTorch weren't used because they would add latency and reduce interpretability for no accuracy benefit on this feature set.
Every training run is versioned: models/<version>/model.joblib + metadata.json (metrics, hyperparameters, feature importances, training row count), with a models/LATEST pointer file the app reads by default. A Markdown evaluation report is generated automatically into reports/.
Web layer (app/app.py) A Streamlit dashboard with:
A live SYSTEM OK / FAULT DETECTED status banner with fault probability.
Live Plotly trend charts for temperature/voltage/vibration with the fault thresholds drawn as reference lines.
An alert feed panel, plus a structured logger.warning("FAULT DETECTED | ...") log line on every alert — this is what the CloudWatch metric filter in infra/main.tf watches for in production, driving an SNS notification independent of anyone watching the screen.
A historical log viewer (backed by the SQLite store) with a CSV download button.
The active model version and its headline metrics, so it's always clear which model is serving predictions.
Infrastructure (infra/) Terraform provisions: an ECR repository, an S3 bucket for data/model artifact backups, an ECS Fargate service running the Streamlit container behind an Application Load Balancer, and a CloudWatch Logs → metric filter → SNS alerting pipeline. Fargate was chosen over Lambda (fights Streamlit's long-lived connections) or raw EC2 (unnecessary ops overhead) — it's the lowest-friction way to run an always-on containerized web app without managing servers.

2. Local development / quick start


Open the URL Streamlit prints (default http://localhost:8501). Click Start Stream in the sidebar to begin simulated live ingestion, or wire simulate_sensor_reading() in app/app.py to your real sensor feed / message queue.

Running with Docker locally


The model is trained once at image build time so the container starts serving predictions immediately.

3. Retraining on your real data

Replace the mock generators in data/data_pipeline.py (generate_mock_sensor_data, generate_mock_log_data) with real ingestion — e.g. reading from S3 exports, a Kafka topic, or a database query — while keeping the same output schema:
Sensor frame: timestamp, sensor_id, temperature, voltage, vibration
Log frame: timestamp, sensor_id, severity, message
Everything downstream (clean_sensor_data, clean_log_data, engineer_features, label_data, persist_to_sqlite) works unchanged as long as those columns are present. Then simply re-run:

This produces a new models/<version>/ artifact, updates models/LATEST, and writes a fresh report to reports/. The dashboard picks up the new LATEST version automatically on next restart (or call load_versioned_model(version="vXXXXXXXX_XXXXXX") directly in app/app.py to pin a specific version).

4. Deploying to AWS

Prerequisites

An AWS account with credentials configured (aws configure)
Terraform >= 1.5
Docker

Step 1 — Provision infrastructure (creates the ECR repo first)


On this first apply, container_image is blank, so the ECS task definition points at <ecr_repo_url>:latest, which doesn't exist yet — the service will fail to start tasks until you push an image. Note the ecr_repository_url output.

Step 2 — Build and push the image


Step 3 — Roll the service onto the new image


Step 4 — Open the dashboard


Step 5 — Subscribe to fault alerts


Confirm the subscription email, and you'll get notified whenever the dashboard logs a fault — independent of whether anyone is watching it.

Redeploying after a new model or code change


ECS performs a rolling deployment automatically.

Tearing everything down


5. User guide (dashboard)

Area What it does Status banner (top) Green "SYSTEM OK" or blinking red "FAULT DETECTED," with live fault probability. Start / Stop Stream (sidebar) Toggles live simulated ingestion. Point simulate_sensor_reading() at a real feed to replace the simulator. Refresh interval / fault likelihood sliders Tune how often new readings arrive and how often the simulator leans toward fault-like conditions (demo-only controls). Live Sensor Trends Plotly line chart of temperature/voltage/vibration with fault-threshold reference lines. Active Alert Feed Rolling list of the last 50 fault alerts raised in this session. Historical Data (sidebar) Table of the most recent 100 of the last 500 SQLite-stored readings, with a Download Full History (CSV) button for the complete set. Active Model panel (sidebar) Shows which model version is serving predictions and its headline accuracy/precision/recall, so you always know what's live. Clear Live Buffer Resets the in-memory chart buffer (does not delete SQLite history).

Streaming/programmatic access to the data

The historical store is a plain SQLite database at data_store/telemetry.db, table sensor_features. For a proper streaming API, wrap load_from_sqlite() (in data/data_pipeline.py) behind a small FastAPI/Flask endpoint, or point a BI tool directly at the SQLite file for read-only access. For production scale, swap SQLite for RDS/Timestream/S3+Athena — the pipeline functions (clean_sensor_data, engineer_features, label_data) are storage- agnostic and don't need to change.

6. Evaluation reports

Every training run writes a report to reports/evaluation_report_<version>.md containing accuracy/precision/recall/F1/ROC-AUC, a confusion matrix, full feature importances, and short interpretability notes. Check reports/ after running python model/model.py for the latest one.

7. Known limitations / next steps

The mock data generators produce a dataset where the label is a deterministic function of two of the four features, so evaluation metrics on synthetic data will look artificially perfect (100%). Once you swap in real, noisier data, expect — and evaluate against — more realistic numbers.
The Streamlit "streaming" loop uses polling (st.rerun() on a timer), not a true WebSocket/async push. This is fine for a dashboard refreshing every 0.5–5s, but if you need sub-second updates at scale, consider moving the live-ingestion path to a small FastAPI + WebSocket service with Streamlit as a read-only view, or a purpose-built streaming dashboard framework.
The Terraform stack uses your account's default VPC to keep first-deploy friction low. For a production environment, replace the data.aws_vpc/data.aws_subnets lookups with a dedicated VPC module (private subnets for ECS, public only for the ALB).
SNS alerting is wired to email/SMS/HTTPS subscribers generically; swap in a Slack/PagerDuty webhook subscription on the same topic for richer on-call routing.
Like this project

Posted Sep 3, 2026

Developed a real-time fault detection platform using sensor data and a Random Forest model.