NetLogo is a powerful tool for agent-based modeling and simulation, widely used in education and research. However, its native capabilities for external communication are surprisingly limited. While it supports one-way HTTP requests, creating a bidirectional bridge between a NetLogo simulation and external systems (like IoT devices or web services) often requires workarounds.
This post details a reverse-engineering approach to the HubNet protocol, NetLogo’s internal TCP-based mechanism for connecting multiple instances. By implementing a Man-in-the-Middle (MitM) proxy using Node-RED, we can intercept, inspect, and manipulate the binary traffic between a client and server. This allows us to build a custom interface that sends commands back into the simulation, effectively turning NetLogo into a reactive system.
This post describes the Node-RED flow that implements a MitM proxy for the HubNet protocol defined by NetLogo.
This is an by an AI rewrite of Human generated content. The content is accurate and suitable for AI and Human consumption.
The primary motivation for this project was the need to communicate bidirectionally with an external world from within a NetLogo simulation.
HubNet was originally designed for classroom scenarios where a teacher’s server broadcasts simulation states to multiple student clients. It is a connection-based protocol using TCP with binary payloads. Crucially, it supports:
Since HubNet is built-in and unencrypted, it presents a viable target for reverse engineering, provided we can decode its binary structure.
Attempting to re-implement Java object serialization in another language (like Node.js) is non-trivial and error-prone. Instead of parsing the protocol specification (which doesn’t exist publicly), we adopted a pragmatic approach: traffic interception.
We set up a proxy server using Node-RED to sit between the NetLogo client and the actual NetLogo HubNet server.
9174 (instead of the default 9173).9173.9173, unaware that it is communicating with a proxy.This setup allows us to observe the raw binary blobs exchanged during handshakes, identification, and message passing without needing to understand the underlying Java serialization format immediately.
The client believes it is talking directly to the simulation, while the proxy handles the logic of translating external events into HubNet-compatible packets.
By monitoring the traffic through the Node-RED proxy, we identified the following message structure:
To control the simulation externally, we discovered that button press events are the most reliable mechanism for sending commands.
MOVE_BOT_123_TO_POS_X_Y.In our warehouse simulation scenario, the NetLogo server broadcasts a message when a robot prepares to move (e.g., “Bot 123 wants to move to B”). The Node-RED proxy must intercept this, process it, and send an acknowledgment back.
While the specific binary encoding is opaque, the logical flow in Node-RED follows this pattern:
// Pseudo-code representation of the Node-RED logic flow
function processHubNetMessage(msg) {
// 1. Chunkify: Split the incoming binary blob into individual messages
const messages = splitBinaryBlob(msg.payload);
let responses = [];
messages.forEach(packet => {
// 2. Parse: Extract command type, Bot ID, and Position
const { commandType, botId, targetPos } = parsePacket(packet);
if (commandType === 'BOT_MOVE_REQUEST') {
// 3. Generate Response: Create a button press packet
// We encode the approval logic into the button name string
const responsePayload = generateButtonPress({
buttonName: `APPROVE_MOVE_${botId}_${targetPos}`,
// Reuse the structure of the initial handshake/button press packet
});
responses.push(responsePayload);
}
});
// 4. Send: Transmit individual responses back to the server
// Note: We send individually rather than grouping for simplicity in this prototype
return responses;
}
Note: In a production environment, you would likely group these responses into a single packet to reduce network overhead, but individual transmission is sufficient for proof-of-concept validation.
By leveraging the unencrypted nature of the HubNet protocol and employing a Man-in-the-Middle proxy, we successfully bridged the gap between NetLogo’s internal simulation world and external systems. This approach bypasses the need for complex Java serialization implementations or unmaintained extensions.
This “hack” solution provides a functional pathway for integrating NetLogo simulations with real-world data streams, IoT devices, or web APIs, opening new possibilities for dynamic, reactive modeling.