Industrial IoT Automation with n8n: No-Code Workflow Integration
Introduction
In industrial facilities, managing data from dozens of sensors can become complex. Alerting, reporting, ERP system integration – all require separate development effort. n8n, an open-source workflow automation platform, simplifies these processes with a visual no-code interface.
In this article, we examine how to automate data flows from our ZMA Data Acquisition and GDT Digital Transmitter devices using n8n, without writing code.
What is n8n?
n8n (nodemation) is an automation platform that connects applications and services. The open-source alternative to Zapier/Make.
Key Features
✅ Open Source: Self-hosted, full control
✅ Visual Interface: Workflow design with drag & drop
✅ 300+ Integrations: MQTT, HTTP, Email, Slack, SAP, databases
✅ Code Support: JavaScript when needed
✅ Low Latency: Real-time triggers
n8n vs Alternatives
| Feature | n8n | Zapier | Make (Integromat) |
|---|---|---|---|
| Open Source | ✅ Yes | ❌ No | ❌ No |
| Self-Hosted | ✅ Yes | ❌ No | ❌ No |
| MQTT Support | ✅ Native | ❌ No | ⚠️ Limited |
| Unlimited Workflows | ✅ Yes | ❌ Paid plans | ❌ Paid plans |
| Cost (1000 ops/month) | Free | $19.99 | $9.00 |
System Architecture
┌───────────────────────────────────────────────────┐
│ Factory Network │
│ │
│ ┌─────────┐ MQTT ┌──────────────┐ │
│ │ ZMA/GDT │─────────────────►│ │ │
│ │ Devices │ │ MQTT Broker │ │
│ └─────────┘ │ (Mosquitto) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ n8n │ │
│ │ Automation │ │
│ │ Server │ │
│ └──┬─────┬─────┘ │
└──────────────────────────────────┼─────┼─────────┘
│ │
┌──────────────┘ └─────────────┐
│ │
┌───────▼────────┐ ┌──────────▼────────┐
│ Email / Slack │ │ ERP / Database │
│ Notifications │ │ (SAP, REST API) │
└────────────────┘ └───────────────────┘
n8n Installation (Docker)
docker-compose.yml
version: '3.8'
services:
n8n:
image: n8nio/n8n:latest
container_name: n8n
restart: always
ports:
- '5678:5678'
environment:
- N8N_BASIC_AUTH_ACTIVE=true
- N8N_BASIC_AUTH_USER=admin
- N8N_BASIC_AUTH_PASSWORD=secure_password_123
- N8N_HOST=n8n.factory.local
- WEBHOOK_URL=http://n8n.factory.local:5678
- N8N_PROTOCOL=http
- NODE_ENV=production
volumes:
- n8n_data:/home/node/.n8n
- /var/run/docker.sock:/var/run/docker.sock
volumes:
n8n_data:
Start Services
docker-compose up -d
# Access web interface
# http://localhost:5678
Workflow 1: Tank Weight Alert System
Scenario
Send email and Slack notification when milk tank weight exceeds 90% capacity.
n8n Workflow Configuration
Nodes:
- MQTT Trigger → Listen to topic
factory/tank/+/weight - Function → Calculate fill percentage
- IF → Check if >90%
- Email → Send warning email
- Slack → Post to #production channel
Visual Workflow:
┌──────────────┐
│ MQTT Trigger │
│ Topic: │
│ factory/tank │
│ /+/weight │
└──────┬───────┘
│
▼
┌──────────────┐
│ Function │
│ Calculate % │
└──────┬───────┘
│
▼
┌──────────────┐
│ IF │
│ weight > 90% │
└──┬───────┬───┘
│ │
│ YES │ NO
│ └──► (End)
▼
┌──────────────┐
│ Email │
│ To: ops@ │
└──────┬───────┘
│
▼
┌──────────────┐
│ Slack │
│ #production │
└──────────────┘
MQTT Trigger Node Configuration
{
"protocol": "mqtt",
"host": "192.168.1.10",
"port": 1883,
"topics": "factory/tank/+/weight",
"qos": 1,
"credentials": {
"username": "mqtt_user",
"password": "mqtt_password"
}
}
Function Node (Calculate Fill %)
// Received MQTT message structure:
// { "tank_id": 1, "weight": 4520.5, "capacity": 5000 }
const tankData = items[0].json
const fillPercent = (tankData.weight / tankData.capacity) * 100
return {
json: {
...tankData,
fill_percent: fillPercent,
alert_level: fillPercent > 90 ? 'HIGH' : 'NORMAL',
},
}
Email Node Configuration
{
"fromEmail": "[email protected]",
"toEmail": "[email protected]",
"subject": "⚠️ Tank {{$json.tank_id}} Capacity Alert",
"text": "Tank {{$json.tank_id}} is {{$json.fill_percent}}% full ({{$json.weight}} kg / {{$json.capacity}} kg).\n\nAction required: Prepare for milk collection.",
"html": "<h2>Tank Capacity Alert</h2><p>Tank <strong>{{$json.tank_id}}</strong></p><p>Fill Level: <strong style='color:red'>{{$json.fill_percent}}%</strong></p>"
}
Workflow 2: Daily Production Report
Scenario
Generate Excel report with yesterday's all tank data and email every morning at 08:00.
Workflow
┌──────────────┐
│ Schedule │
│ Cron: 0 8 ** │
└──────┬───────┘
│
▼
┌──────────────┐
│ HTTP Req │
│ GET /api/ │
│ tank_data │
└──────┬───────┘
│
▼
┌──────────────┐
│ Function │
│ Format data │
└──────┬───────┘
│
▼
┌──────────────┐
│ Spreadsheet │
│ Create Excel │
└──────┬───────┘
│
▼
┌──────────────┐
│ Email │
│ + Attachment │
└──────────────┘
HTTP Request Node (Get Data)
{
"method": "GET",
"url": "http://api.factory.local/v1/tank_data",
"qs": {
"date": "{{$now.minus({days: 1}).toFormat('yyyy-MM-dd')}}",
"format": "json"
},
"authentication": "headerAuth",
"headers": {
"Authorization": "Bearer {{$credentials.apiToken}}"
}
}
Function Node (Format for Excel)
// Transform API response to Excel-friendly format
const rawData = items[0].json.data
const formattedData = rawData.map(record => ({
'Tank ID': record.tank_id,
Timestamp: record.timestamp,
'Weight (kg)': record.weight,
'Fill %': Math.round(record.fill_percent),
Status: record.status,
}))
return formattedData.map(row => ({ json: row }))
Spreadsheet Node Configuration
{
"operation": "toFile",
"fileFormat": "xlsx",
"fileName": "Daily_Production_Report_{{$now.toFormat('yyyy-MM-dd')}}.xlsx",
"sheetName": "Tank Data",
"headerRow": true
}
Workflow 3: ERP System Integration
Scenario
When GDT weighing is complete, automatically create production record in SAP ERP system.
Workflow
┌──────────────┐
│ Webhook │
│ /weighing- │
│ complete │
└──────┬───────┘
│
▼
┌──────────────┐
│ Function │
│ Map to SAP │
│ format │
└──────┬───────┘
│
▼
┌──────────────┐
│ HTTP Req │
│ POST SAP API │
│ /production │
└──────┬───────┘
│
▼
┌──────────────┐
│ IF │
│ Success? │
└──┬───────┬───┘
│ │
YES NO
│ │
▼ ▼
┌─────┐ ┌─────┐
│ OK │ │Error│
│ Log │ │Retry│
└─────┘ └─────┘
Webhook Trigger
{
"path": "weighing-complete",
"httpMethod": "POST",
"responseMode": "lastNode",
"authentication": "headerAuth"
}
Example webhook call from HMI:
curl -X POST http://n8n.factory.local:5678/webhook/weighing-complete \
-H "Authorization: Bearer abc123xyz" \
-H "Content-Type: application/json" \
-d '{
"batch_id": "MILK-2025-001",
"tank_id": 1,
"gross_weight": 4850.5,
"tare_weight": 350.0,
"net_weight": 4500.5,
"timestamp": "2025-12-29T14:30:00Z"
}'
Function Node (SAP Format Mapping)
// Map weighing data to SAP production order format
const data = items[0].json
return {
json: {
ProductionOrder: {
OrderNumber: data.batch_id,
Material: 'MILK-RAW',
Quantity: data.net_weight,
QuantityUnit: 'KG',
Plant: '1000',
WorkCenter: 'WEIGHING-01',
StartDate: data.timestamp,
EndDate: data.timestamp,
Status: 'COMPLETED',
},
},
}
HTTP Request to SAP
{
"method": "POST",
"url": "https://sap.factory.com/sap/opu/odata/sap/API_PRODUCTION_ORDER_2_SRV/A_ProductionOrder",
"authentication": "oAuth2",
"bodyContentType": "json",
"body": "={{$json.ProductionOrder}}"
}
Error Handling and Retry Logic
Retry on Failure
// Error Handler Node
const MAX_RETRIES = 3
const currentRetry = $executionId.split('-').length - 1
if (currentRetry < MAX_RETRIES) {
// Exponential backoff
const waitTime = Math.pow(2, currentRetry) * 1000 // 1s, 2s, 4s
return {
json: {
retry: true,
wait_ms: waitTime,
attempt: currentRetry + 1,
},
}
} else {
// Max retries exceeded, send alert
return {
json: {
retry: false,
error: 'Max retries exceeded',
notify_admin: true,
},
}
}
Performance and Scalability
n8n Resource Usage
| Metric | Value |
|---|---|
| CPU | 0.5-1 core (idle) |
| RAM | 512 MB (idle), 2 GB (active) |
| Storage | ~100 MB + workflow data |
| Throughput | ~100 workflows/second |
Scaling for Large Facilities
For 100+ sensors:
- Queue-based processing (MQTT → Redis Queue → n8n)
- Multiple n8n instances (Docker Swarm/Kubernetes)
- Database for workflow results (PostgreSQL)
Conclusion
n8n enables rapid automation of complex data flows in industrial facilities without code. Especially powerful for:
✅ MQTT to Email/Slack alerts
✅ Automated reporting (Excel, PDF)
✅ ERP system integration (SAP, Odoo)
✅ Multi-system workflows
Our ZMA and GDT devices can be easily integrated with n8n via Modbus → MQTT gateway for complete workflow automation.