Introduction
Fastening is one of those things that fades into the background on a manufacturing floor.
Torque tools click all day. Hundreds of operators. Thousands of bolts. Shift after shift. It’s repetitive, predictable-and absolutely unforgiving. One skipped bolt or a rundown performed out of order can quietly turn into a defect, a rework ticket, or a recall that no one wants to explain later.
Because of that, modern tightening tools have grown up. They’re no longer just powered screwdrivers. Today’s controllers enforce standard work, guide operators through sequences, block mistakes before they happen, and refuse to move forward unless every step is done correctly.
And behind every one of those clicks is data.
Torque. Angle. Timestamps. Operator IDs. Batch numbers. Rework flags. Tightening IDs. When that information is tied into product genealogy inside an MES, WMS, ERP, or traceability system, it becomes incredibly valuable. It supports compliance. It strengthens warranty defense. It reveals rework patterns. It turns gut-feel process improvement into something measurable.
The catch? Getting that data out-and sending instructions back-means speaking a language that sits somewhere between IT networking and industrial automation.
That language is Open Protocol.
Open Protocol, Explained Without the Ceremony
If you work around fastening automation long enough, you’ll hear the same names come up again and again. Atlas Copco PowerFocus controllers. Tensor tools. Automotive, aerospace, heavy equipment-anywhere torque accuracy and traceability matter.
These controllers are essentially embedded industrial computers. They run jobs. They validate rundowns. They guide operators. They store historical results. And they expose all of that functionality through Open Protocol.
Open Protocol is an ASCII-based messaging standard published by Atlas Copco. “Open” here doesn’t mean open-source-it means documented and available for anyone to implement. The format is rigid, deliberate, and unapologetically old-school.
Through Open Protocol, external systems can lock or unlock tools, select jobs, push work-order context, subscribe to tightening results, request historical data, and monitor controller state. It’s both a command channel and a data pipeline wrapped into one.
If you speak it correctly, the controller will happily do exactly what you ask. If you don’t, it will ignore you without explanation.
Why Open Protocol Feels Weird to IT Folks
If you’re used to REST APIs and JSON payloads, Open Protocol can feel like stepping back in time.
Like WebSockets, Open Protocol uses a persistent, two-way TCP connection. Messages can arrive at any time, not just in response to a request. Like MQTT, it supports subscriptions-except instead of subscribing to topics, you subscribe to specific MIDs. For example, you can ask the controller to send you MID 0061 every time a tightening completes.
What Open Protocol doesn’t do is abstract anything away. What you send is exactly what the controller sees. That’s intentional. In embedded systems, ambiguity is dangerous.
The result is a lean, deterministic protocol built for precision, not convenience.
What These Controllers Are Actually Capable Of
Once you get past the protocol quirks, the controllers open up quickly.
You can remotely enable or disable tools. You can select predefined jobs or upload dynamic ones on the fly. You can attach work-order context-VINs, batch IDs, sequence numbers-so every tightening is tied to a specific product.
Most importantly, you can subscribe to tightening results.
Every completed rundown generates a MID 0061 message containing torque, angle, OK/NOK status, timestamps, identifiers, and metadata. That stream becomes the heartbeat of the workstation. Historical results can also be requested later, which is invaluable after network hiccups or during investigations.
Beyond tightening data, controllers expose firmware versions, parameters, job states, operating modes, and error conditions. In practice, they behave like small industrial servers built around a torque tool-provided you’re willing to talk to them properly.
A Practical Python Open Protocol Client
Once you understand that the controller communicates using Open Protocol over a persistent TCP connection, the next step is building a client that can keep pace. This is done using straightforward socket programming with Python’s built‑in socket library.
No framework. No SDK. Just something reliable.
The Python client in this project is intentionally minimal. It establishes a connection to the controller, formats and sends messages correctly, listens continuously for responses, and remains running long enough to be genuinely useful. Nothing more. Nothing less.
If you’d rather jump straight to the working code, the full implementation lives on GitHub: Torque-Tool-Lite/integrate.py
Starting the Conversation
Everything begins with a socket.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2.0)
sock.connect((TORQUE_TOOL_IP, TORQUE_TOOL_PORT))
print("Connected to the torque tool.")
Once connected, the real challenge is formatting messages the way Open Protocol expects them.
Speaking Open Protocol Correctly
Every Open Protocol message follows the same basic pattern: a four-character ASCII length, a four-digit MID, a revision, reserved spaces, an optional payload, and a null terminator.
Miss a character, and the controller simply won’t respond.
A small helper function handles this formatting:
def format_message(mid, revision="001", payload=""):
payload_bytes = payload.encode('ascii') if payload else b''
length = 20 + len(payload_bytes) + 1
header = (
f"{length:04}"
f"{int(mid):04}"
f"{revision}"
f" "
f" "
f" "
f" "
).encode('ascii')
return header + payload_bytes + b'\x00'
With that in place, sending messages becomes straightforward:
send_connection_request(sock) # MID 0001
send_LTR_subscription_request(sock) # MID 0060
Under the hood, it’s just structured ASCII sent over TCP—but structure matters.
Listening Without Missing Anything
Controllers don’t wait for permission to talk. Tightening results arrive the moment a bolt is finished. If your code isn’t listening, the data is gone.
That’s why the client runs a dedicated receiver thread whose only job is to read bytes, reassemble messages, and push them into a queue.
class SocketReceiver(threading.Thread):
def run(self):
while not self._stop.is_set():
data = self.sock.recv(4096)
self._buf.extend(data)
while len(self._buf) >= 4:
length = int(self._buf[0:4].decode('ascii'))
if len(self._buf) < length:
break
msg = bytes(self._buf[:length])
del self._buf[:length]
self.out_q.put(msg)
Think of it as the ears of the system. It doesn’t interpret anything. It just listens.
Staying Alive With Heartbeats
One detail that’s easy to miss: controllers don’t like silence.
If your client goes quiet for too long, the controller assumes it died and drops the connection. To prevent that, a lightweight heartbeat thread sends MID 9999 at a fixed interval.
def send_keep_alive_loop(sock, stop_event, interval=10.0):
while not stop_event.is_set():
sock.sendall(format_message("9999"))
stop_event.wait(interval)
It’s simple, but it’s the difference between a stable integration and one that fails randomly in production.
Where Everything Comes Together
With networking handled in the background, the main loop becomes refreshingly boring—in the best way.
while True:
msg = msg_q.get()
if msg is None:
break
mid = msg[4:8].decode('ascii')
if mid == "0002":
parse_mid_0002(msg)
elif mid == "0061":
parse_mid_0061(msg)
No sockets. No threading logic. Just reacting to meaningful events.
This is where you plug in your real work: storing results, enforcing workflows, triggering alarms, or feeding data into MES, ERP, or analytics systems.
Beyond Listening: Steering the Tool
The full repository goes further than just consuming data.
It includes helpers for selecting jobs, restarting or aborting them, defining dynamic jobs, pulling historical tightening results by ID, and enabling or disabling the tool entirely. In other words, it doesn’t just observe the controller—it can actively guide it.
With those building blocks, you’re only a few steps away from a full integration. Add a database for persistence. Add a work-instruction model to enforce sequences. Publish results via OPC UA or MQTT. The foundation is already there.
If you want to explore the working implementation complete with error handling, message parsing, job control helpers, and all the logic described above. You can find it on my GitHub:Torque-Tool-Lite/integrate.py
Feel free to clone it, break it, improve it, or adapt it for your own line and if you want to add more messages to your implementation I suggest taking a look at The Open Protocol Specification
Final Thoughts
Open Protocol isn’t flashy. It isn’t forgiving. But it’s honest.
If you take the time to understand it and wrap it in a clean, reliable client, it becomes a powerful bridge between shop-floor reality and enterprise systems. Torque tools stop being isolated devices and start becoming first-class participants in your data ecosystem.
The technology is already in your tools. The rest is just listening carefully—and responding deliberately.
If this subject interests you then check out my article on automation and industry 4.0 as whole Here.
Comments