Tutorial 50: Manufacturing IoT & Predictive Maintenance¶
Overview¶
Build an end-to-end predictive maintenance and OEE analytics solution for a discrete manufacturing plant with 200 CNC machines across 4 production lines running 24/7 operations.
What you will learn:
- Ingest IoT sensor telemetry through Eventstream
- Build a medallion architecture for manufacturing data
- Compute OEE (Availability x Performance x Quality)
- Detect anomalies with z-score analysis
- Generate predictive maintenance risk scores
- Visualize with Power BI Direct Lake dashboards
Time to complete: ~90 minutes
Architecture¶
graph TD
A[IoT Hub<br/>MQTT / OPC-UA] -->|Eventstream| B[Bronze<br/>bronze_manufacturing_sensors]
B --> C[Silver<br/>silver_manufacturing_health]
C --> D1[Gold<br/>gold_manufacturing_oee]
C --> D2[Gold<br/>gold_maintenance_predictions]
D1 --> E[Power BI<br/>OEE Dashboard]
D2 --> E
A -->|Real-time| F[Eventhouse<br/>KQL Anomaly Detection]
F --> G[Data Activator<br/>Alerts]
D2 --> H[Digital Twin Builder<br/>3D Plant View]
style A fill:#0078D4,color:white
style B fill:#CD7F32,color:white
style C fill:#C0C0C0,color:black
style D1 fill:#FFD700,color:black
style D2 fill:#FFD700,color:black
style E fill:#F2C811,color:black
style F fill:#0078D4,color:white Prerequisites¶
- Microsoft Fabric workspace (F64 capacity)
- Lakehouse:
lh_bronze,lh_silver,lh_gold - Python 3.10+ (for data generation)
- Azure IoT Hub (optional -- for real-time path)
Step 1: Generate Synthetic Data¶
Generate realistic sensor telemetry with degradation patterns.
from generators.manufacturing.sensor_generator import ManufacturingSensorGenerator
# Initialize generator (200 machines, 10% showing degradation)
gen = ManufacturingSensorGenerator(seed=42, num_machines=200, degradation_pct=0.10)
# Generate sensor readings
sensors_df = gen.generate(num_records=50000, show_progress=True)
print(f"Generated {len(sensors_df):,} sensor readings")
print(sensors_df.head())
# Generate work orders
work_orders_df = gen.generate_work_orders(num_orders=500)
print(f"Generated {len(work_orders_df):,} work orders")
# Export to Parquet for Fabric upload
gen.to_parquet(sensors_df, "output/bronze_manufacturing_sensors.parquet")
gen.to_parquet(work_orders_df, "output/bronze_manufacturing_work_orders.parquet")
Verification:
- 50,000 sensor records generated
- 500 work orders generated
- Parquet files in
output/directory - Machine types include CNC, press, robot, conveyor
Step 2: Upload to Fabric Lakehouse¶
- Open your Fabric workspace
- Navigate to
lh_bronzeLakehouse - Click Get data > Upload files
- Upload both Parquet files to
Files/output/
Verification:
- Files visible in
lh_bronze/Files/output/
Step 3: Run Bronze Notebook¶
Import and run the Bronze ingestion notebook.
- In your workspace, click Import notebook
- Select
notebooks/bronze/54_manufacturing_sensors.py - Attach to your Lakehouse
- Click Run all
What this does:
- Reads raw Parquet sensor data
- Validates critical fields (sensor_id, machine_id, timestamp)
- Adds Bronze metadata (_bronze_ingested_at, _bronze_batch_id)
- Writes to
bronze_manufacturing_sensorsDelta table
Verification:
-
bronze_manufacturing_sensorstable created - All critical field null checks pass
- Machine type distribution shows all 4 types
Step 4: Run Silver Notebook¶
Import and run the Silver transformation notebook.
- Import
notebooks/silver/54_manufacturing_aggregated.py - Attach to Lakehouse
- Click Run all
What this does:
- Aggregates sensor data into 1-minute windows
- Computes avg, max, stddev per sensor per machine
- Calculates z-scores over 1-hour rolling windows
- Flags anomalies where z-score > 3.0
- Adds days-since-last-maintenance
Verification:
-
silver_manufacturing_healthtable created - Anomaly rate between 5-15% (expected with 10% degradation)
- All sensor aggregation columns populated
Step 5: Run Gold Notebook¶
Import and run the Gold analytics notebook.
- Import
notebooks/gold/54_manufacturing_oee.py - Attach to Lakehouse
- Click Run all
What this does:
- Assigns shifts (Day/Swing/Night)
- Computes OEE = Availability x Performance x Quality
- Calculates energy consumption per unit
- Generates predictive maintenance risk scores (0-100)
- Classifies machines: NORMAL / MONITOR / SOON / IMMEDIATE
Verification:
-
gold_manufacturing_oeetable created -
gold_maintenance_predictionstable created - Average OEE between 60-85%
- Some machines flagged as IMMEDIATE or SOON
Step 6: Explore Results¶
OEE by Machine Type¶
SELECT machine_type,
ROUND(AVG(oee) * 100, 1) AS avg_oee_pct,
ROUND(AVG(availability) * 100, 1) AS avg_availability_pct,
ROUND(AVG(quality) * 100, 1) AS avg_quality_pct,
COUNT(*) AS shift_count
FROM lh_gold.gold_manufacturing_oee
GROUP BY machine_type
ORDER BY avg_oee_pct DESC
Machines Needing Maintenance¶
SELECT machine_id,
machine_type,
ROUND(maintenance_risk_score, 1) AS risk_score,
ROUND(oee * 100, 1) AS oee_pct,
recommended_action
FROM lh_gold.gold_maintenance_predictions
WHERE maintenance_risk_score > 60
ORDER BY maintenance_risk_score DESC
Energy Efficiency Leaders¶
SELECT machine_id,
machine_type,
ROUND(AVG(energy_kwh_per_unit), 2) AS avg_energy_per_unit,
ROUND(AVG(oee) * 100, 1) AS avg_oee_pct
FROM lh_gold.gold_manufacturing_oee
GROUP BY machine_id, machine_type
ORDER BY avg_energy_per_unit ASC
LIMIT 10
Step 7: Build Power BI Dashboard (Optional)¶
- In your workspace, click New > Report > Pick a dataset
- Select
gold_manufacturing_oee(Direct Lake) - Create the following visuals:
| Visual | X-Axis | Y-Axis | Filter |
|---|---|---|---|
| Card | -- | AVG(oee) | -- |
| Bar chart | machine_type | AVG(oee) | -- |
| Line chart | shift_date | AVG(oee) | machine_type |
| Matrix | machine_id | maintenance_risk_score | risk > 60 |
| Gauge | -- | AVG(availability) | -- |
Step 8: Real-Time Path (Optional)¶
For sub-minute anomaly detection, configure Eventstream + Eventhouse:
- Create Eventstream connected to Azure IoT Hub
- Route to Eventhouse for KQL anomaly queries
- Create KQL Queryset with the vibration anomaly query from the use case doc
- Configure Data Activator to alert when anomaly count > 5 in 10 minutes
IEC 62443 Security Checklist¶
| Control | Status | Notes |
|---|---|---|
| OT/IT network segmentation | Required | Separate VLANs, firewall rules |
| Industrial DMZ | Required | IoT Edge gateway in DMZ |
| TLS 1.2+ for all data in transit | Required | IoT Hub enforces TLS |
| X.509 device certificates | Required | No shared keys |
| One-way data flow (OT -> IT) | Required | No cloud-to-OT commands |
| Fabric private endpoints | Recommended | Network isolation |
| Sensitivity labels | Recommended | Auto-apply "Confidential" |
Troubleshooting¶
| Issue | Resolution |
|---|---|
| No anomalies detected | Increase degradation_pct in generator (e.g., 0.20) |
| OEE always 100% | Check Silver anomaly flags; verify Bronze data has variance |
| Empty predictions table | Ensure Silver table has data; check shift assignment logic |
| Slow Silver notebook | Reduce Bronze data volume or increase Spark executors |
Key Concepts¶
OEE Formula¶
OEE = Availability x Performance x Quality
Availability = Run Time / Planned Time
Performance = (Ideal Cycle x Parts) / Run Time
Quality = Good Parts / Total Parts
Predictive Maintenance Score¶
Risk = (Vibration x 0.35) + (Temperature x 0.25)
+ (Current x 0.20) + (Maintenance Age x 0.20)
0-40: NORMAL -- standard schedule
40-60: MONITOR -- increase inspections
60-80: SOON -- schedule within 7 days
80+: IMMEDIATE -- schedule within 24 hours
Related Resources¶
- Use Case: Manufacturing Predictive Maintenance
- Digital Twin Builder
- Real-Time Intelligence
- Network Security
- Tutorial 04: Real-Time Analytics
Next Steps¶
- Connect real IoT devices via Azure IoT Hub
- Train a survival analysis model for RUL (Remaining Useful Life)
- Integrate with Digital Twin Builder for 3D visualization
- Set up Data Activator alerts for production notifications
- Expand to supply chain and inventory optimization