This repository contains the implementation of a real-time IoT data pipeline that demonstrates the fundamental architecture of Digital Twin systems. The project simulates a physical temperature sensor using Python, transmits data over the internet using the MQTT (Message Queuing Telemetry Transport) publish/subscribe protocol, and ingests that data in real-time into an AnyLogic Digital Twin model.
Physical Layer → Communication Layer → Digital Twin Layer
[Python Sensor] → [MQTT Broker] → [AnyLogic Model]
(Publisher) (HiveMQ Cloud) (Subscriber)
The system demonstrates:
- Real-time data streaming from physical sensors to digital models
- Publish/Subscribe messaging pattern for decoupled communication
- Visual state representation that changes based on sensor data
- Time-series visualization of incoming telemetry data
- Automatic reconnection and error handling for production resilience
PhysicalSensor/
│
├── sensor_edge.py # Basic MQTT publisher (lab version)
├── sensor_edge_robust.py # Production-ready MQTT publisher with error handling
├── lab.md # Lab instructions
├── README.md # This file
└── .venv/ # Python virtual environment (auto-created)
- Operating System: Windows 10/11, macOS 10.15+, or Linux (Ubuntu 20.04+)
- Python: Version 3.8 or higher
- AnyLogic: Personal Learning Edition (PLE) or higher
- Internet Connection: Required for MQTT broker communication
- RAM: Minimum 4GB (8GB recommended for AnyLogic)
- Disk Space: 500MB for dependencies
- Python Package Manager: pip or pip3
- Java Runtime: JRE 8+ (typically bundled with AnyLogic)
- Text Editor: VS Code, Sublime Text, or any code editor
- Terminal Access: Command Prompt (Windows), Terminal (macOS/Linux)
# Install UV if not already installed
brew install uv
# Clone or navigate to the project directory
cd ~/Downloads/PhysicalSensor
# Create virtual environment
uv venv
# Activate virtual environment
source .venv/bin/activate # On macOS/Linux
# OR
.venv\Scripts\activate # On Windows
# Install MQTT library
uv pip install paho-mqtt# Navigate to project directory
cd ~/Downloads/PhysicalSensor
# Create virtual environment
python3 -m venv .venv # On macOS/Linux
# OR
python -m venv .venv # On Windows
# Activate virtual environment
source .venv/bin/activate # On macOS/Linux
# OR
.venv\Scripts\activate # On Windows
# Install MQTT library
pip install paho-mqtt-
Navigate to Maven Central Repository:
https://repo1.maven.org/maven2/org/eclipse/paho/org.eclipse.paho.client.mqttv3/1.2.5/ -
Download the JAR file:
org.eclipse.paho.client.mqttv3-1.2.5.jar -
Save the JAR file in your project directory (same folder as your AnyLogic model)
# Check Python version
python --version
# Verify MQTT library installation
python -c "import paho.mqtt; print('MQTT library installed successfully')"
# Test MQTT connectivity
python -c "import paho.mqtt.publish as publish; publish.single('test/topic', 'test', hostname='broker.hivemq.com'); print('MQTT broker accessible')"This version implements the original lab specification:
# Activate virtual environment
source .venv/bin/activate # macOS/Linux
# OR
.venv\Scripts\activate # Windows
# Run the sensor
python sensor_edge.pyNote: This version may experience connection timeouts after extended operation due to public broker rate limiting.
This production-ready version includes:
- Automatic reconnection logic
- Connection state management
- Error handling and recovery
- QoS 1 message delivery confirmation
- Clean shutdown handling
# Activate virtual environment
source .venv/bin/activate # macOS/Linux
# OR
.venv\Scripts\activate # Windows
# Run the robust sensor
python sensor_edge_robust.pyStarting Physical Sensor Simulation...
Client ID: sensor_2547
Publishing to: ucf/ids6742/bulent/machine/temp
Attempting to connect to broker.hivemq.com...
Connected successfully to broker.hivemq.com
Published Data: 102.05 °C
Published Data: 101.09 °C
Published Data: 103.15 °C
...
To stop the sensor: Press Ctrl+C
- Open AnyLogic
- File → New → Model
- Model Name:
RealTime_Twin_MQTT - Model Time Units:
seconds - Click Finish
- In Projects view, click on
RealTime_Twin_MQTT(top-level) - In Properties → Dependencies section
- Click green plus (+) under "Jar files and class folders"
- Browse and select
org.eclipse.paho.client.mqttv3-1.2.5.jar - Click OK
- Open Main diagram
- From Agent palette, drag
Variableto canvas - Configure:
- Name:
currentTemperature - Type:
double - Initial value:
100.0
- Name:
-
Machine Representation:
- From Presentation palette, drag
Rectangle - In Properties → Appearance → Fill color
- Click static/dynamic switch (=) to make dynamic
- Enter:
currentTemperature >= 110.0 ? red : lime
- From Presentation palette, drag
-
Real-time Chart:
- From Analysis palette, drag
Time Plot - Configure:
- Data update:
Update automatically - Recurrence time:
0.5 seconds - Time window:
60 seconds - Add data item:
- Title:
Live Temp - Value:
currentTemperature
- Title:
- Data update:
- From Analysis palette, drag
-
Click empty space in Main diagram
-
Properties → Advanced Java → Imports section:
import org.eclipse.paho.client.mqttv3.*;
-
Properties → Advanced Java → Additional class code:
MqttClient client;
-
Properties → Agent actions → On startup:
try { // Connect to HiveMQ public broker client = new MqttClient("tcp://broker.hivemq.com:1883", MqttClient.generateClientId(), null); // Define message handler client.setCallback(new MqttCallback() { public void connectionLost(Throwable cause) { traceln("Connection lost!"); } public void messageArrived(String topic, MqttMessage message) throws Exception { double incomingTemp = Double.parseDouble(new String(message.getPayload())); currentTemperature = incomingTemp; traceln("Received: " + incomingTemp + " on topic: " + topic); } public void deliveryComplete(IMqttDeliveryToken token) {} }); // Connect and subscribe client.connect(); client.subscribe("ucf/ids6742/bulent/machine/temp"); traceln("Digital Twin Connected and Listening..."); } catch (MqttException e) { e.printStackTrace(); }
-
Properties → Agent actions → On destroy:
try { if(client != null && client.isConnected()) { client.disconnect(); } } catch (MqttException e) { }
- Click Run (or press F5)
- Check console for: "Digital Twin Connected and Listening..."
- Machine rectangle should be green (temperature < 110°C)
- Time plot should show flat line at 100.0°C initially
- In AnyLogic, run your model
- Verify "Digital Twin Connected and Listening..." in console
- Rectangle should be green
# In terminal
cd ~/Downloads/PhysicalSensor
source .venv/bin/activate
python sensor_edge_robust.py- Time plot updates every second with new temperature data
- Rectangle turns RED when temperature exceeds 110°C
- Rectangle turns GREEN when temperature drops below 110°C
- Console shows received messages
- Stop Python script (Ctrl+C) - Digital Twin maintains last state
- Restart Python script - Digital Twin resumes receiving data
- Simulate network issues - Robust version auto-reconnects
# Solution: Install in virtual environment
source .venv/bin/activate
pip install paho-mqttCause: Public broker rate limiting or connection limits
Solution: Use sensor_edge_robust.py which implements:
- Random client IDs to avoid conflicts
- Automatic reconnection with backoff
- Connection state management
Solution: Ensure JAR file is properly added:
- Check JAR file exists in project directory
- Verify path in Dependencies section
- Restart AnyLogic if necessary
Checklist:
- Topic names must match EXACTLY between Python and AnyLogic
- Check firewall settings (port 1883 must be open)
- Verify internet connectivity
- Check AnyLogic console for error messages
# Add flush=True to print statements for immediate output
print(f"Published Data: {payload} °C", flush=True)The simulation uses random walk: temp += random.uniform(-1.0, 2.5)
- Average drift: +0.75°C per second
- To stabilize, adjust range to:
random.uniform(-1.75, 1.75)
- Protocol: MQTT v3.1.1
- Broker: broker.hivemq.com (public)
- Port: 1883 (unencrypted)
- QoS Levels:
- QoS 0: At most once (fire-and-forget)
- QoS 1: At least once (acknowledged) - Used in robust version
- QoS 2: Exactly once (not used here)
- Topic Structure:
ucf/ids6742/{username}/machine/temp - Payload: String representation of float (e.g., "102.45")
- Frequency: 1 message per second
- Size: ~6-8 bytes per message
- Latency: ~50-200ms (depends on network)
- Throughput: 1 msg/sec (configurable)
- Connection Overhead: ~2KB initial handshake
- Bandwidth: ~10 bytes/second during operation
- No encryption: Data transmitted in plaintext
- No authentication: Anyone can publish/subscribe
- Public visibility: All topics are accessible
For production systems, implement:
- TLS/SSL encryption (port 8883)
- Username/password authentication
- Access Control Lists (ACLs)
- Private MQTT broker deployment
# In sensor_edge_robust.py
topics = {
"temperature": "ucf/ids6742/bulent/machine/temp",
"pressure": "ucf/ids6742/bulent/machine/pressure",
"vibration": "ucf/ids6742/bulent/machine/vibration"
}Add control commands from AnyLogic to Python:
// In AnyLogic
client.publish("ucf/ids6742/bulent/machine/control", "STOP");import csv
with open('sensor_log.csv', 'a') as f:
writer = csv.writer(f)
writer.writerow([time.time(), temp])// In AnyLogic messageArrived method
if(incomingTemp > 115.0) {
// Trigger alarm
showMessage("CRITICAL: Temperature exceeds safety threshold!");
}This lab demonstrates:
- IoT Architecture: Understanding publish/subscribe messaging patterns
- Digital Twin Concepts: Real-time synchronization between physical and digital
- Protocol Implementation: Working with MQTT for IoT communication
- System Integration: Connecting heterogeneous systems (Python + Java)
- Error Handling: Building resilient distributed systems
- Real-time Visualization: Creating responsive dashboards
- Industrial IoT (IIoT)
- Industry 4.0
- Cyber-Physical Systems
- Digital Thread
- Predictive Maintenance
- Smart Manufacturing
Course: IDS 6742 - Real-Time Simulation Modeling for Digital Twins
Instructor: Dr. Bulent Soykan
Institution: University of Central Florida
For technical issues with the lab, please ensure you have:
- Followed all installation steps
- Checked the troubleshooting section
- Verified network connectivity
- Reviewed error messages in both Python and AnyLogic consoles
This educational material is provided for academic purposes as part of the IDS 6742 course curriculum. Students are encouraged to experiment, modify, and extend the code for learning purposes.
Last Updated: March 2026