Twitter
Google plus
Facebook
Vimeo
march-2026

Tool Life Tracking with Lua

TIPS FROM THE EXPERT Date: 26 March 2026

Tool Life Tracking
with Lua

We recently received a question from a MASSO user:

“I would like to track my tool life. Can this be done with MASSO?”

It’s a great question—and one that reflects how serious builders think about production, efficiency, and consistency.

The short answer is: yes, it can.

With MASSO’s Lua capability, you can build a practical tool life tracking system that works alongside your workflow—without adding unnecessary complexity.

The Approach
Using Lua triggers for:

  • Tool Change (Before Tool Change)
  • End of Job

you can track how long each tool is used during a job and automatically send that data to myWorkshop PRO.

From there, you can store and analyse the data in your own spreadsheet or database.

The reason for using these triggers is simple: at every tool change, the current runtime is captured. This means that even if a job is paused or rewound, the tool usage time remains accurate and continues to accumulate correctly.

Sending the data at the end of the job ensures you get a complete, per-job summary of tool usage. This also gives you a clearer understanding of production costs, including the ability to allocate tool wear to specific jobs.

It’s also possible to extend this further by exporting additional data at the end of the job— such as the G-code file name or job count—allowing you to track tool usage against individual jobs with greater detail.

Implementation
The full Lua scripts are provided below and should be added to:

  • Before Tool Change trigger
  • End of Job trigger

You can:

  • Enter them directly on the controller
  • Or use the myWorkshop cloud-based Lua editor for easier setup and management

The MASSO Lua Custom Scripts are available in full at the end of this article and also at https://forums.masso.com.au/threads/tool-life-tracking-with-lua-custom-scripts.5379/

How It Works

1. Track Tool Usage During the Job
Each time a tool change is triggered:

  • the Lua custom script will check for a table called toolUsage and if none is found, will create it
  • the Lua custom script will check the for variable called lastToolTime and if the variable doesn’t exist, it is created and set to zero

Next, the tool number and use time of the current tool is captured in a set of local variables:

The tool number is collected

The controller’s accumulated job runtime is read and converted to seconds

Then this number is compared to a variable that stores the time already used up by other tools in the job

Next, the time already used up is compared to the current time to give the tool use time

After this, the information is stored to the table:

If the tool is already in the table, its previous time used is added to the extra time used and updated, if it doesn’t exist already, it will be added to the table

And the time used up so far is stored for next time

At the end of the before tool change script, we need to return true so an alarm is not triggered and your MASSO controller knows the process was successful.

2. Capture Final Tool Data at End of Job
At the end of the job ((triggered by an M30 rewind or M02 end of job) :

As each new tool is used, it will add it to the table checking to see if that tool has already been used in a job.

The script will check again, and in the case only one tool was used for the job, will create the table the same as before,

The tool is now added to the table, or if the table is already created, it will check the current tool and add it to the table and update its time.

The data in the table is now sent to your myWorkshop PRO inbox

The time is calculated into hours minutes and seconds

Each tool entry in the table is added to the message to be sent

The message is sent to myWorkshop

At the end of the job, the table is cleared out, ready for the next job, a short delay is added to ensure the data can be collected before the table is cleared

3. Send Data to myWorkshop PRO
The script then:

  • Converts total runtime into hours, minutes, and seconds
  • Formats a clean summary message
  • Sends it directly to your myWorkshop PRO inbox

4. Use the Data Your Way
Once received in myWorkshop PRO, the data can be:

  • Copied into a spreadsheet
  • Logged in a database
  • Used for tool replacement planning
  • Analysed for production efficiency

If needed, you can switch the separator from ” | “ to “,” to make the output CSV- compatible for direct import.

Why This Matters
Tool life tracking isn’t just about data—it’s about confidence in production.

With this approach, you can:

  • Understand real tool usage across jobs
  • Plan maintenance before failures happen
  • Reduce downtime
  • Build more predictable, repeatable workflows

And importantly, you’re doing it using tools already built into MASSO—no external systems required.



-- ===========================
--  Before Tool Change
-- ===========================

toolUsage = toolUsage or {}
lastToolTime = lastToolTime or 0

-- Capture current tool usage one last time
local currentTool = M.tool.get_current()
if currentTool then
local toolName = M.tool.get_name(currentTool) or "Unnamed"
local runTimeTable = M.sys.get_job_runtime() or {}
local hh = runTimeTable.hour or 0
local mm = runTimeTable.min or 0
local ss = runTimeTable.sec or 0
local totalSeconds = (hh * 3600) + (mm * 60) + ss

local deltaSeconds = totalSeconds
if lastToolTime then
deltaSeconds = totalSeconds - lastToolTime
if deltaSeconds < 0 then deltaSeconds = 0 end
end

-- Add or update table entry
local entry = toolUsage[currentTool]
if entry then
entry.seconds = entry.seconds + deltaSeconds
else
toolUsage[currentTool] = { name = toolName, seconds = deltaSeconds }
end
lastToolTime = totalSeconds
end

return true


-- ===========================
--  END OF JOB TOOL REPORT
-- ===========================

toolUsage = toolUsage or {}
lastToolTime = lastToolTime or 0

-- Capture current tool usage one last time
local currentTool = M.tool.get_current()
if currentTool then
local toolName = M.tool.get_name(currentTool) or "Unnamed"
local runTimeTable = M.sys.get_job_runtime() or {}
local hh = runTimeTable.hour or 0
local mm = runTimeTable.min or 0
local ss = runTimeTable.sec or 0
local totalSeconds = (hh * 3600) + (mm * 60) + ss

local deltaSeconds = totalSeconds
if lastToolTime then
deltaSeconds = totalSeconds - lastToolTime
end

-- Add or update table entry
local entry = toolUsage[currentTool]
if entry then
entry.seconds = entry.seconds + deltaSeconds
else
toolUsage[currentTool] = { name = toolName, seconds = deltaSeconds }
end
end

-- ===========================
--  SEND TOOL USAGE IN ONE LINE
-- ===========================

local msg = "Tool Usage Report: "

for toolNum, data in pairs(toolUsage) do
local seconds = data.seconds or 0
local hh = math.floor(seconds / 3600)
local mm = math.floor((seconds % 3600) / 60)
local ss = math.floor(seconds % 60)
local formatted = string.format("%02d:%02d:%02d", hh, mm, ss)

-- Add this tool to the message, separated by " | "
msg = msg .. string.format("T%02d-%s:%s | ", toolNum, data.name or "?", formatted)
end

-- Remove the trailing separator
msg = msg:sub(1, -4)

-- Send all in one message
M.sys.send_myworkshop_message(msg)

-- Clear table for next job
M.sys.delay(1000)
toolUsage = nil
lastToolTime = nil

Final Thoughts
This is a great example of how MASSO gives you the flexibility to extend your machine’s capability—while keeping the system simple, reliable, and focused on real work.

Because control systems should support your workflow—not complicate it.