kial Thank you very much for your help! My code required a few adjustments related to the luamqtt library, such as using ioloop_mt:iteration()
, as well as modifications specific to CoppeliaSim, like ensuring the coroutine is resumed at least once per simulation step.
For anyone who might find it useful, here is the working code, it connects CoppeliaSim to a local MQTT broker in a non-blocking way :
function sysCall_init()
sim = require('sim')
-- Initialize MQTT
package.path = package.path .. ";C:/Program Files/CoppeliaRobotics/CoppeliaSimEdu/lua/mqtt/?.lua"
print("Package path updated:", package.path)
local mqtt = require("mqtt")
local ioloop = require("mqtt.ioloop").get() -- Get the default ioloop instance
if not mqtt then
error("Failed to load MQTT library. Check the path and ensure the library exists.")
end
-- Create MQTT client
client = mqtt.client{
uri = "127.0.0.1:1883",
id = "robot_client",
clean = true
}
if not client then
error("Failed to create MQTT client.")
end
print("Created MQTT client:", client)
-- Set up the MQTT client on events
client:on{
connect = function(connack)
if connack.rc ~= 0 then
print("Connection to broker failed:", connack:reason_string(), connack)
return
end
print("Connected to broker:", connack)
-- Subscribe to the topic after connection
assert(client:subscribe{
topic = "robot/commands",
qos = 2,
callback = function(suback)
print("Subscribed to topic:", suback)
end
})
end,
message = function(msg)
assert(client:acknowledge(msg))
print("Received message:", msg.topic, msg.payload)
end,
error = function(err)
print("MQTT client error:", err)
end,
close = function()
print("MQTT connection closed")
end
}
-- Attach client to the ioloop
local success, err = pcall(function()
ioloop:add(client)
end)
if not success then
print("Failed to add client to ioloop:", err)
return
end
print("Client added to ioloop")
-- Create the coroutine for the MQTT loop
mqttCoroutine = coroutine.create(function()
while true do
local success, err = pcall(function()
ioloop:iteration(0.1) -- Small timeout to prevent excessive CPU usage
end)
if not success then
print("Error in ioloop iteration:", err)
end
coroutine.yield() -- Yield control back to CoppeliaSim
end
end)
end
-- Resume the coroutine in the sensing function
function sysCall_sensing()
if coroutine.status(mqttCoroutine) ~= 'dead' then
local ok, errorMsg = coroutine.resume(mqttCoroutine)
if errorMsg then
error(debug.traceback(mqttCoroutine, errorMsg), 2)
end
end
end