| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| simulator.exe | 2026-02-28 | 120.1 kB | |
| README.md | 2026-02-28 | 23.8 kB | |
| Totals: 2 Items | 143.9 kB | 5 |
Bufferstack.IO Open Protocol Advanced Simulator
A production-grade Atlas Copco nutrunner controller simulator for Open Protocol R2.16.0 integration testing, OPC UA gateway development, and Node-RED prototyping.
Copyright © 2026 Harshad Joshi, Bufferstack.IO Analytics Technology LLP, Pune, Maharashtra, India
-
GitHub: https://github.com/hj91
-
Project: Bufferstack.IO Open Protocol → OPC UA Gateway
Table of Contents
Overview
This simulator emulates an Atlas Copco nutrunner tightening controller over TCP using the Open Protocol R2.16.0 specification. It is written in C and targets Windows (MinGW / MSYS2), compiling to a single self-contained executable with no external dependencies beyond the Windows socket library.
It is a C port of the advanced-traceability-simulator-rev-1-to-7.js JavaScript reference implementation, preserving identical simulation behaviour while adding lower-level protocol control, raw frame tracing, multi-client support, and a 1-hour runtime limit.
The simulator is the companion test tool for the Bufferstack.IO node-nutrunner-open-protocol library and the Open Protocol → OPC UA Gateway project. It allows full end-to-end integration testing of gateway software, Node-RED flows, and OPC UA clients against a realistic controller simulation — without needing physical Atlas Copco hardware.
Why This Exists
Developing and testing Open Protocol integrations against real nutrunner hardware is expensive, requires physical access to factory equipment, and cannot easily simulate NOK (not-OK) fault conditions on demand. This simulator solves that by:
-
Running entirely on a Windows development machine.
-
Generating realistic tightening results with random torque, angle, VIN, operator, and joint data.
-
Injecting controlled NOK fault scenarios (torque too low, torque too high, angle deviation, cross-thread detection).
-
Supporting all MID 0061 revisions 1 through 7 simultaneously across multiple clients.
-
Sending MID 0900 trace curve data (torque and angle) for every tightening cycle.
-
Providing raw ASCII frame dumps on the console for protocol-level debugging.
Features
Protocol Coverage
-
MID 0001 / 0002 — Communication start and acknowledgement
-
MID 0005 — Generic positive acknowledgement (sent in response to subscription MIDs)
-
MID 0004 — Error frame
-
MID 0018 — Parameter set selection
-
MID 0038 — Job selection
-
MID 0040 / 0041 — Tool data upload request and reply
-
MID 0042 / 0043 — Disable and enable tool
-
MID 0060 — Subscribe to tightening results (MID 0061), revision negotiation
-
MID 0061 — Tightening result, Revisions 1 through 7
-
MID 0062 — Tightening result acknowledge (received and silently accepted)
-
MID 0070 — Alarm subscribe
-
MID 0071 — Alarm (sent on NOK cycles)
-
MID 0900 — Trace curve data subscribe
-
MID 0901 — Trace curve data unsubscribe
-
MID 9999 — Keep-alive echo
Simulation
-
5 pre-configured tightening joints with realistic torque and angle ranges.
-
Random VIN selection from a pool of 4 simulated vehicle IDs.
-
Random operator selection from a pool of 4 simulated operator IDs.
-
Batch management with automatic rollover every 10 cycles.
-
~15% random NOK injection across 4 distinct fault types.
-
Torque values rounded to 2 decimal places (matching JS
toFixed(2)behaviour). -
Angle values floored to integer degrees.
-
Realistic prevail torque, self-tap torque, rundown angle, and current monitoring values.
Infrastructure
-
Up to 16 simultaneous TCP clients.
-
Per-client MID 0061 revision tracking.
-
Per-client MID 0900 curve subscription tracking.
-
Thread-per-client architecture with critical section locking.
-
Non-blocking accept loop with keyboard polling.
-
Blocking send with WSAEWOULDBLOCK retry.
-
1-hour runtime limit with graceful shutdown and countdown warnings.
Requirements
-
Windows 7 or later (uses Winsock2,
GetLocalTime,CreateThread) -
GCC via MinGW or MSYS2, or MSVC
Build
No external libraries. No CMake. No dependencies. Single file, single command.
Bash
gcc -o simulator simulator-shareware.c -lws2_32 -lm
Run
The simulator starts immediately, prints the configuration banner, and begins listening on TCP port 4545. Auto-mode starts generating tightening cycles every 5 seconds as soon as a client connects.
Bash
./simulator
Example startup output:
Plaintext
========================================================================
BUFFERSTACK.IO OPEN PROTOCOL ADVANCED SIMULATOR
© Harshad Joshi, 2026 - Bufferstack.IO Analytics Technology LLP
========================================================================
Port: 4545 Station: AdvancedStation01 Tool Serial: SN-TC-20260001
Auto-Mode: ON (5000ms interval)
MID 0061 Rev 1 - Rev 7 (negotiated per subscriber)
MID 0900: ENABLED Raw Trace: ENABLED Runtime: Max 1 hour auto-shutdown
Joints:
1. Engine Mount FL 45-55 Nm 80-120 deg
2. Engine Mount FR 45-55 Nm 80-120 deg
3. Transmission Mount 60-70 Nm 90-130 deg
4. Wheel Hub Bolt 120-140 Nm 360-420 deg
5. Suspension Arm 75-85 Nm 110-150 deg
Controls: q=Quit m=Manual b=Batch j=Job p=Pset 1-7=Rev r=Layout
Configuration
All configuration is via #define constants at the top of simulator-shareware.c. No runtime arguments are needed. To change the port, tool serial, or any other parameter, edit the relevant #define and recompile. The build is fast — a few seconds at most.
| Constant | Default | Description |
|---|---|---|
PORT |
4545 |
TCP listen port |
STATION_NAME |
AdvancedStation01 |
Station name returned in MID 0002 |
TOOL_SERIAL |
SN-TC-20260001 |
Tool serial number (used in MID 0041 and MID 0061) |
CONTROLLER_SN |
CTRL-SN-12345678 |
Controller serial number |
AUTO_MODE |
1 |
1 = auto-generate cycles, 0 = manual only |
AUTO_INTERVAL |
5000 |
Milliseconds between automatic tightening cycles |
SEND_CURVES |
1 |
1 = send MID 0900 after each cycle, 0 = disable |
CURVE_POINTS |
20 |
Number of torque/angle data points per curve |
DEFAULT_REV |
7 |
MID 0061 revision assigned to new clients before negotiation |
MAX_RUNTIME_SEC |
3600 |
Auto-shutdown after this many seconds (1 hour) |
Keyboard Controls
The simulator polls for keypresses in the main accept loop without blocking. All controls work while clients are connected.
| Key | Action & Description |
|---|---|
q / Q |
Graceful shutdown — closes all client sockets and exits |
m / M |
Manual trigger — instantly generates one tightening cycle |
b / B |
Force a batch change — increments batch counter and logs the new batch ID |
j / J |
Increment Job — increments the current job number |
p / P |
Increment Pset — increments the current parameter set (pset) number |
1 – 7 |
Force Revision — forces all currently connected clients to MID 0061 revision N |
r / R |
Print Layout — prints the full MID 0061 field layout for the current default revision |
Simulated Joints and NOK Scenarios
Each tightening cycle selects a joint, VIN, and operator at random and generates torque and angle values within the joint's defined range, with ±10% variance.
Joints
| ID | Name | Torque Min (Nm) | Torque Max (Nm) | Angle Min (°) | Angle Max (°) |
|---|---|---|---|---|---|
| 1 | Engine Mount FL | 45.0 | 55.0 | 80 | 120 |
| 2 | Engine Mount FR | 45.0 | 55.0 | 80 | 120 |
| 3 | Transmission Mount | 60.0 | 70.0 | 90 | 130 |
| 4 | Wheel Hub Bolt | 120.0 | 140.0 | 360 | 420 |
| 5 | Suspension Arm | 75.0 | 85.0 | 110 | 150 |
NOK Fault Injection
Approximately 15% of cycles are injected as NOK. The fault type is selected randomly. NOK cycles trigger a MID 0071 alarm in addition to the MID 0061 result.
| Probability | Fault Code | Description |
|---|---|---|
| ~5% | E001 |
Torque Too Low — final torque falls below joint minimum |
| ~5% | E002 |
Torque Too High — final torque exceeds joint maximum |
| ~3% | E003 |
Angle Deviation — final angle exceeds joint maximum |
| ~2% | E004 |
Cross-Thread Detection — both torque and angle severely under-range |
Supported MIDs
Incoming (RX)
Any unrecognised MID receives a MID 0005 positive acknowledgement.
| MID | Description |
|---|---|
0001 |
Communication Start |
0018 |
Select Parameter Set |
0038 |
Select Job |
0040 |
Tool Data Upload Request |
0042 |
Disable Tool |
0043 |
Enable Tool |
0060 |
Subscribe to Tightening Results (revision negotiation) |
0062 |
Tightening Result Acknowledge |
0070 |
Alarm Subscribe |
0900 |
Trace Curve Data Subscribe |
0901 |
Trace Curve Data Unsubscribe |
9999 |
Keep-Alive |
Outgoing (TX)
| MID | Description |
|---|---|
0002 |
Communication Start Acknowledge |
0004 |
Error |
0005 |
Command Accepted (positive ACK) |
0041 |
Tool Data Upload Reply |
0061 |
Tightening Result (Rev 1–7) |
0071 |
Alarm |
0900 |
Trace Curve Data |
MID 0061 Revision Details
MID 0061 revision is negotiated per client via MID 0060. Each client stores its own revision independently. The revision controls how many fields are appended to the result payload. Use keyboard key r at runtime to print the full byte-offset field layout for the current revision.
| Rev | Cumulative Fields Added |
|---|---|
| 1 | Cell ID, Channel ID, Controller Name, VIN, Job ID, Pset No, Batch Size, Batch Counter, Tighten Status, Torque Status, Angle Status, Torque Min/Max/Target/Final, Angle Min/Max/Target/Final, Timestamp, Last Pset Change TS, Batch Status, Tightening ID, Job Seq, Sync ID, Tool Serial, Full Timestamp |
| 2 | Strategy Options, Current Monitor Status, Prevail Monitor Status, Prevail Comp Status, Tightening Error Status, Rundown Angle, Current Min/Max/Final, Self-Tap Torque, Prevail Torque Min/Max/Final |
| 3 | Operator ID (Identifier Part 2) |
| 4 | Joint Identifier (Part 3), Job-Pset Identifier (Part 4) |
| 5 | Customer Error Code |
| 6 | Prevail Torque Compensate Value, Angle Error Status |
| 7 | Batch ID, Tool Serial (extended, 25 chars) |
MID 0041 — node-open-protocol Compatibility
Critical note for integrators using the
node-open-protocolnpm package (st-one-io).
The Open Protocol R2.16.0 specification (Table 74) defines MID 0041 Rev 1 with fields 01 through 11 in sequential order, with toolSerialNumber = 14 characters. However, the node-open-protocol library parses MID 0041 with a different internal layout:
-
toolSerialNumberis read as 10 characters (not 14). -
lastCalibrationDateis located at byte offset 10 from the start of the payload — immediately after the tool serial, with fields 02–08 placed after the date.
This was determined experimentally by observing what values appeared in the lastCalibrationDate field for different payload constructions.
Layout used by this simulator (node-open-protocol compatible)
| Field | Name | Offset | Width | Notes |
|---|---|---|---|---|
| 01 | toolSerialNumber |
0 | 10 | Truncated from TOOL_SERIAL |
| 09 | lastCalibrationDate |
10 | 19 | YYYY-MM-DD:HH:MM:SS format |
| 02 | customerToolNumber |
29 | 6 | |
| 03 | toolType |
35 | 2 | 01 = torque wrench |
| 04 | tighteningDirection |
37 | 1 | 1 = clockwise |
| 05 | motorSize |
38 | 2 | |
| 06 | openEndType |
40 | 2 | 00 = none |
| 07 | controllerID |
42 | 4 | |
| 08 | numberOfTightenings |
46 | 10 | Increments with each cycle |
| 10 | controllerSerialNumber |
56 | 10 | Truncated from CONTROLLER_SN |
| 11 | calibrationValue |
66 | 6 | In cNm (Nm × 100), 005000 = 50.00 Nm |
Total payload: 72 bytes
If you are using a different Open Protocol client library, verify its MID 0041 field layout independently. The spec-compliant layout (fields 01–11 in order, toolSerial=14, calibDate at offset 41) may be required instead.
MID 0900 — Trace Curve Data
After each tightening cycle, the simulator spawns a background thread that sends MID 0900 trace curve data 150ms after the MID 0061 result, to simulate the real controller's asynchronous curve delivery. Curve data is only sent to clients that have subscribed via MID 0900. Unsubscribe via MID 0901.
Two traces are included per frame:
-
Trace type 01 — Torque: 20 points, eased curve (ease-in-out from 0 to final torque), with ±3% random noise. Values in cNm.
-
Trace type 02 — Angle: 20 points, linear ramp from 0 to final angle, with ±2% random noise. Values in 0.1° units.
Frame Format
All Open Protocol frames use the standard 20-byte ASCII header. Frames are NUL-terminated on the wire. The receiver accumulates bytes until a NUL is found, then dispatches the complete message. Partial frames are buffered per client.
Plaintext
Bytes [0:4] — Total frame length, 4-digit zero-padded integer (includes header)
Bytes [4:8] — MID, 4-digit zero-padded string
Bytes [8:11] — Revision, 3-digit zero-padded integer
Byte — No-Ack flag (1 char)[1]
Bytes [12:14] — Station ID (2 chars)
Bytes [14:16] — Spindle ID (2 chars)
Bytes [16:20] — Sequence number (4 chars)
Bytes [20:] — Payload (variable length)
Console Output
The simulator prints colour-coded output to the console using ANSI escape codes:
-
Green: OK tightening result or TX frame
-
Red: NOK tightening result, alarm, or error
-
Cyan: RX frame
-
Yellow: Batch change event or field layout dump
-
Grey: Timestamps and frame hex/ASCII trace
Every TX and RX frame is dumped in hex + ASCII at 32 bytes per line, with byte offset annotations. This provides full protocol-level visibility for debugging without a separate packet capture tool.
Architecture Notes
-
One thread per client: Each accepted client socket runs in its own thread, which handles all receive buffering and message dispatch for that connection.
-
Critical section locking: All access to the shared client array, result counter, batch ID, and controller state is protected by a single
CRITICAL_SECTION. -
Non-blocking accept loop: The server socket is set to non-blocking mode (
FIONBIO=1) so the main thread can poll for keypresses between accept calls. Accepted client sockets are explicitly reset to blocking mode. -
Async curve and alarm delivery: MID 0900 curves and MID 0071 alarms are delivered from separate short-lived threads with deliberate delays (150ms and 100ms respectively) to simulate real controller timing.
-
NUL-terminated framing: The receive buffer accumulates raw bytes and scans for NUL terminators to extract complete frames, correctly handling TCP stream fragmentation.
Known Quirks and Compatibility Notes
node-open-protocol(st-one-io)
The lastCalibrationDate field in MID 0041 is read at byte offset 10, not the spec-defined offset 41. See the MID 0041 section above for the full compatible layout.
- ANSI Colours on Windows
Console colours require Windows 10 version 1511 or later (Virtual Terminal Processing). On older Windows versions the ANSI escape sequences will appear as literal characters. Redirect output to a file if needed: ./simulator > log.txt.
- 1-Hour Runtime Limit
The simulator automatically shuts down after 3600 seconds. This is intentional for the shareware release. Warning messages are printed at 55, 50, 30, 10, and 5 minutes remaining. To run indefinitely, increase MAX_RUNTIME_SEC and recompile.
- VIN and Operator Pools
VINs and operator IDs are randomly selected from small hardcoded pools. For production-like testing, expand the VINS[] and OPERATORS[] arrays in the source.
Disclaimer
This software is provided for development and testing purposes only. It is not intended for use in production environments, safety-critical systems, or real manufacturing lines. Bufferstack.IO Analytics Technology LLP and Harshad Joshi accept no liability for any damages, data loss, or equipment malfunction arising from the use of this software. The simulator does not control any physical hardware. It is a pure software simulation intended solely for protocol integration testing.
License
All rights reserved.
© 2026 Harshad Joshi, Bufferstack.IO Analytics Technology LLP, Pune, Maharashtra, India.
This software is part of the Bufferstack.IO Open Protocol OPC UA Gateway project. Redistribution or use outside of its intended development and testing purpose is not permitted without explicit written permission from the author.
Built with ❤️ in Pune, India — Bufferstack.IO Analytics Technology LLP