[ST Edge] - Driver/Device timers

Is there a way get a list of outstanding timers (one-shot or scheduled) from the driver class? I need to be able to cancel any outstanding timers at a point in my driver, but don’t see a way to do that from the driver documentation.

I know the alternative - keep track of them in a table myself…

@TAustin

Not yet, but I’ll check with the engineers if this is going to be addressed at some point.

For the moment you should be able to track your all your device timers under device.thread.timersand cancel them using the device.thread:cancel_timer method (for better reference, check the st.thread.Thread documentation).


Update

Just for reference, the direct use of st.thread.Thread module is not recommended, as it may lead to blocking operations within the driver.

For this reason, is better to use its implementation (e.g. device.thread) to prevent blocking the main thread.

Thanks Erick - For now, I’ve started tracking my own timers.

I have not explored the use of the thread libraries yet. I was hoping for some clarity in the documentation on why/when it’s needed (vs. just the regular driver stuff), how to use, and ideally an example. All that I see right now is just the reference API, but nothing addressing the aforementioned.

Thanks.

Check the lifecycles flow from the SampleDrivers/lightbulb-lan-esp8266 sample as it has a few references on how/when to schedule certain functions.

It also provides a reference to cancel the timers for devices that are being removed from the driver’s context.

Sorry for being obtuse, Erick - I was referring to more info on the threads library, not timers. :grimacing:

1 Like

I agree with you, even if it is a low-level API that is not intended for explicit use, it might be useful to know what’s happening down there. So, added to the report! = )


As at the moment the device.thread.timers doesn’t provide a human-readable reference of the timer/schedule, I think you might find useful the following references to keep track of your timers/schedules:

  • driver.device_cache[<device_id>].thread.watched_sockets
  • driver.message_handlers

These resources provide the reference of the driver and device timer/schedules including the label, which can help you to debug and maintain your timers.

1 Like

Ok thank-you!

Is that really the case? Since it’s documented (threads) in the driver reference it looks like it is intended for explicit use in certain cases. It’s those certain cases I’d like to understand better. (Patrick had also pointed me to threads when we were talking about possible blocking problems in one of my drivers.)

1 Like

It can be considered as such because it is not only a big part of the driver model but also a feasible block to build driver features that are not exclusively attached to the platform.

For example the register_socket API to initialize TCP/UDP servers (see example).

Hi @erickv

I don’t know how to use register_socket api.

Would you let me know example code?

This is my code.

local tcp = socket.tcp()
tcp:settimeout(0)
tcp:connect(‘192.168.1.110’, 5000)

device.thread:register_socket(
– device, – device.thread
tcp,
function ()
local s, status, partial = tcp:receive()
if s ~= nil then
print(s)
end
end,
‘TCP Socket’)

Error log >> Lua: runtime error: [string “cosock”]:222: non-wakeable socket

Yea, funny enough the code that Erick posted as an example did not use register_socket!

I haven’t used it myself, but my understanding of it is that it’s just part of a Lua cosock implementation of the standard socket select function you’d find in other languages (C). So register_socket is the same thing as FD_SET in Linux, for example. This reference page has some example code at the bottom.

I noticed you don’t have a bind statement in the snippet you posted. Maybe try adding:

local listen_ip = "0.0.0.0"
local listen_port = 0
assert(tcp:bind(listen_ip, listen_port), "LAN tcp socket")
2 Likes

(replying to older thread) - I also ran into the 222 non-wakeable socket. Tracked it down that the internals.setuprealsocketwaker isn’t getting run. Can’t see why not, since the code seems to be there. But calling it myself on the socket before doing register_socket does eliminate the error (and I confirmed that the function IS missing from the object-table before I made the call). If I can get register_socket to work I’ll post up a snippet (so far no love).

Did anyone ever crack the code on this non wakeable error? I have a working mdns library that utlizes its own timeout, but would like to modify it to utilize driver:register_channel_handler instead. Rough code looks like this:

local sock = socket.udp()
sock:setoption('reuseaddr', true)
sock:setsockname('*', 0)
sock:setoption('ip-add-membership', { interface = '0.0.0.0', multiaddr = mdns.MULTICAST_IP })

driver:register_channel_handler(sock, function()
    local data, ip, port = udp:receivefrom()
    -- do something with response
end, 'discovery')

while should_continue() do
    log.debug('discovery sending broadcast')
    sock:sendto(mdns:query(service, mdns.RR_TYPE_PTR), mdns.MULTICAST_IP, mdns.MULTICAST_PORT)
    socket.sleep(10)
end

FYI, for those that find this thread…I was getting the non wakeable error due to a difference in the socket implementation running on the hub. I inadvertently required:

local socket = require 'socket'

instead of requiring this…

local socket = require 'cosock.socket'

@fison67 / @edleno You may want to double check that, although I am sure you have since moved on from your original comments.

1 Like