03 - Software Stack
IoT platforms, middleware, and software tools for hardware integration
Table of Contents
- Platform Overview
- IoT Middleware
- Message Brokers
- Time-Series Databases
- Visualization Tools
- Development Tools
- Recommended Stack
1. Platform Overview
IoT Platform Comparison
| Platform | Type | Best For | Pricing |
|---|---|---|---|
| AWS IoT Core | Cloud | Enterprise, scalable | Pay-per-use |
| Azure IoT Hub | Cloud | Microsoft ecosystem | Pay-per-use |
| Google Cloud IoT | Cloud | ML integration | Pay-per-use |
| ThingsBoard | Self-hosted | Full control | Open source |
| Ignition | On-premise | Industrial SCADA | License-based |
Platform Selection Matrix
┌─────────────────────────────────────────┐
│ DECISION MATRIX │
├─────────────────────────────────────────┤
│ │
Cloud-Native ───┼─── AWS IoT / Azure IoT Hub │
│ ↑ │
│ │ Scalability │
│ │ │
Hybrid ───────┼─── ThingsBoard + Cloud Storage │
│ │ │
│ │ Control │
│ ↓ │
On-Premise ─────┼─── Ignition + Local Database │
│ │
└─────────────────────────────────────────┘
2. IoT Middleware
2.1 Node-RED (Recommended for Prototyping)
# Installation
npm install -g node-red
# With industrial nodes
npm install node-red-contrib-modbus
npm install node-red-contrib-opcua
npm install node-red-contrib-mqtt-broker
Use Cases:
- Visual flow programming for sensor data
- Protocol conversion (Modbus → MQTT)
- Quick prototyping and testing
Sample Flow (JSON):
{
"id": "sensor-to-ml-flow",
"nodes": [
{
"type": "modbus-read",
"name": "Read pH Sensor",
"address": "0",
"quantity": "1"
},
{
"type": "function",
"name": "Transform Data",
"func": "msg.payload = { parameter: 'pH', value: msg.payload[0] / 100 }; return msg;"
},
{
"type": "mqtt out",
"name": "Publish to MQTT",
"topic": "sensors/plant1/pH"
}
]
}
2.2 Apache Kafka (Production-Grade)
# Docker Compose for Kafka
docker-compose up -d kafka zookeeper
docker-compose.yml:
version: "3.8"
services:
zookeeper:
image: confluentinc/cp-zookeeper:7.4.0
environment:
ZOOKEEPER_CLIENT_PORT: 2181
kafka:
image: confluentinc/cp-kafka:7.4.0
depends_on:
- zookeeper
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
Use Cases:
- High-throughput sensor data streaming
- Event sourcing for audit trails
- Stream processing with Kafka Streams
2.3 Kepware KEPServerEX (Industrial Standard)
Features:
- OPC-UA server for 150+ device drivers
- Connect to Siemens, Allen-Bradley, Modbus devices
- REST/MQTT gateway for cloud connectivity
Configuration:
<!-- KEPServerEX Channel Configuration -->
<Channel>
<Name>WaterTreatmentPlant</Name>
<Driver>Modbus TCP/IP Ethernet</Driver>
<Device>
<Name>pH_Sensor_01</Name>
<IPAddress>192.168.1.100</IPAddress>
<Port>502</Port>
<Tags>
<Tag Name="pH_Value" Address="40001" DataType="Float"/>
<Tag Name="Temperature" Address="40003" DataType="Float"/>
</Tags>
</Device>
</Channel>
3. Message Brokers
3.1 EMQX (Recommended)
# Docker installation
docker run -d --name emqx \
-p 1883:1883 \
-p 8083:8083 \
-p 8084:8084 \
-p 8883:8883 \
-p 18083:18083 \
emqx/emqx:5.3.0
Features:
- 100M+ connections support
- Built-in rule engine
- WebSocket support
- Kubernetes ready
EMQX Rule for Data Routing:
-- Route sensor data to ML API
SELECT
payload.sensorId as sensor_id,
payload.parameter as param,
payload.value as value,
timestamp as ts
FROM
"sensors/#"
WHERE
payload.quality = 'good'
3.2 Mosquitto (Lightweight)
# Installation
sudo apt install mosquitto mosquitto-clients
# Configuration
cat > /etc/mosquitto/mosquitto.conf << EOF
listener 1883
allow_anonymous false
password_file /etc/mosquitto/passwd
EOF
3.3 Broker Comparison
| Feature | EMQX | Mosquitto | HiveMQ |
|---|---|---|---|
| Connections | 100M+ | 100K | 10M+ |
| Clustering | Yes | No | Yes |
| Rule Engine | Yes | No | Yes |
| WebSocket | Yes | Plugin | Yes |
| License | Apache 2.0 | EPL | Commercial |
4. Time-Series Databases
4.1 InfluxDB (Recommended)
# Docker installation
docker run -d --name influxdb \
-p 8086:8086 \
-v influxdb-data:/var/lib/influxdb2 \
influxdb:2.7
Schema Design:
Measurement: water_quality
Tags:
- plant_id: "plant_01"
- sensor_id: "ph_sensor_001"
- location: "inlet"
Fields:
- pH: 7.2
- temperature: 25.5
- quality_score: 0.95
Timestamp: 2024-12-08T10:30:00Z
Query Example:
-- Get average pH for last hour
SELECT mean("pH")
FROM "water_quality"
WHERE time > now() - 1h
GROUP BY time(5m), "plant_id"
4.2 TimescaleDB (PostgreSQL Extension)
-- Create hypertable for sensor data
CREATE TABLE sensor_readings (
time TIMESTAMPTZ NOT NULL,
sensor_id TEXT NOT NULL,
parameter TEXT NOT NULL,
value DOUBLE PRECISION,
quality TEXT
);
SELECT create_hypertable('sensor_readings', 'time');
-- Create continuous aggregate
CREATE MATERIALIZED VIEW sensor_hourly
WITH (timescaledb.continuous) AS
SELECT
time_bucket('1 hour', time) AS bucket,
sensor_id,
parameter,
AVG(value) as avg_value,
MIN(value) as min_value,
MAX(value) as max_value
FROM sensor_readings
GROUP BY bucket, sensor_id, parameter;
4.3 Database Comparison
| Feature | InfluxDB | TimescaleDB | QuestDB |
|---|---|---|---|
| Query Language | Flux/InfluxQL | SQL | SQL |
| Compression | High | Good | Excellent |
| Joins | Limited | Full SQL | Full SQL |
| Learning Curve | Medium | Low (SQL) | Low |
5. Visualization Tools
5.1 Grafana (Recommended)
# Docker installation
docker run -d --name grafana \
-p 3000:3000 \
-v grafana-data:/var/lib/grafana \
grafana/grafana:10.2.0
Dashboard JSON Example:
{
"dashboard": {
"title": "Water Quality Monitoring",
"panels": [
{
"type": "timeseries",
"title": "pH Levels",
"targets": [
{
"query": "from(bucket: \"sensors\") |> range(start: -1h) |> filter(fn: (r) => r._measurement == \"water_quality\" and r._field == \"pH\")"
}
]
},
{
"type": "gauge",
"title": "Current BOD",
"targets": [
{
"query": "from(bucket: \"sensors\") |> range(start: -5m) |> filter(fn: (r) => r._field == \"BOD\") |> last()"
}
]
}
]
}
}
5.2 Ignition Perspective (Industrial HMI)
Use Cases:
- Plant floor displays
- Operator interfaces
- Mobile-friendly dashboards
5.3 Custom Dashboard (Next.js)
Your existing dashboard already supports real-time visualization. Integrate with:
rechartsfor charts (already in use)socket.iofor real-time updatesreact-queryfor data fetching
6. Development Tools
6.1 Required npm Packages
# IoT Protocol Libraries
npm install mqtt # MQTT client
npm install node-opcua # OPC-UA client
npm install modbus-serial # Modbus RTU/TCP
# Stream Processing
npm install kafkajs # Kafka client
npm install rxjs # Reactive programming
# Database Clients
npm install @influxdata/influxdb-client # InfluxDB
npm install pg # PostgreSQL/TimescaleDB
# Real-time Communication
npm install socket.io # WebSocket server
npm install socket.io-client # WebSocket client
6.2 Required Python Packages
# requirements-iot.txt
paho-mqtt==1.6.1 # MQTT client
opcua==0.98.13 # OPC-UA client
pymodbus==3.5.4 # Modbus client
kafka-python==2.0.2 # Kafka client
influxdb-client==1.38.0 # InfluxDB client
redis==5.0.1 # Redis client
6.3 Docker Services
# docker-compose.iot.yml
version: "3.8"
services:
mqtt:
image: emqx/emqx:5.3.0
ports:
- "1883:1883"
- "8083:8083"
- "18083:18083"
influxdb:
image: influxdb:2.7
ports:
- "8086:8086"
volumes:
- influxdb-data:/var/lib/influxdb2
grafana:
image: grafana/grafana:10.2.0
ports:
- "3001:3000"
volumes:
- grafana-data:/var/lib/grafana
redis:
image: redis:7-alpine
ports:
- "6379:6379"
node-red:
image: nodered/node-red:3.1
ports:
- "1880:1880"
volumes:
- nodered-data:/data
volumes:
influxdb-data:
grafana-data:
nodered-data:
7. Recommended Stack
For Neilsoft Integration
┌─────────────────────────────────────────────────────────────────┐
│ RECOMMENDED STACK │
├──────────────────────────────────────────────────────── ─────────┤
│ │
│ LAYER TECHNOLOGY REASON │
│ ───── ────────── ────── │
│ │
│ Protocol Gateway Kepware KEPServerEX Industry standard │
│ │
│ Message Broker EMQX Scalable, rules │
│ │
│ Stream Processing Apache Kafka High throughput │
│ │
│ Time-Series DB InfluxDB Purpose-built │
│ │
│ Cache Redis Real-time access │
│ │
│ Visualization Grafana + Custom Flexible │
│ │
│ Edge Runtime Node-RED + Docker Easy deployment │
│ │
│ ML Serving FastAPI + TF Serving Production ready │
│ │
└─────────────────────────────────────────────────────────────────┘
Quick Start Script
#!/bin/bash
# start-iot-stack.sh
echo "Starting IoT development stack..."
# Start core services
docker-compose -f docker-compose.iot.yml up -d
# Wait for services
sleep 10
# Initialize InfluxDB bucket
docker exec influxdb influx bucket create \
--name sensors \
--org Edubotx \
--retention 30d
echo "IoT stack is ready!"
echo "- MQTT Broker: localhost:1883"
echo "- InfluxDB: localhost:8086"
echo "- Grafana: localhost:3001"
echo "- Node-RED: localhost:1880"
Next Steps
- Proceed to 04-PROTOCOL-ADAPTERS.md for protocol implementation
- Review 05-API-INTEGRATION.md for API endpoints
Last Updated: December 2024