Search code examples
multithreadingtimerluasleephammerspoon

How to implement periodic task in Hammerspoon initialization?


I thought it would be great to be notified when my network connectivity dies or is revived, so I put this in my Hammerspoon init.lua:

ping = nil
previousStatus = nil
function pingCallback(server, eventType, ...)
  hs.alert.show(eventType)

  if eventType == "receivedPacket" 
  then
    newStatus = "success"
  else
    if eventType == "didFail" or eventType == "sendPacketFailed" 
    then
      newStatus = "failure"
    end
  end

  if not (newStatus == previousStatus)
  then
    hs.alert.show(string.format("Network status changed to %s", newStatus))
    previousStatus = newStatus
  end
end

while(true)
do
  ping = hs.network.ping.ping("google.com", 5, 1.0, 2.0, "any", pingCallback)
  os.execute("sleep 15")
end

The problem is the sleep. It sleeps Hammerspoon itself, making it hang. What I really need is a thread or timer, or maybe to start a different OS process. What should I do?


Solution

  • Hammerspoon has a timer. You might replace your while loop with something like:

    function pingGoogle()
      hs.network.ping.ping("google.com", 5, 1.0, 2.0, "any", pingCallback)
    end
    
    googlePinger = hs.timer.new(15, pingGoogle)
    googlePinger:start()
    

    Some other things to consider:

    • Start/stop the ping timer based on Network Reachability. No need to poll with a ping if the route to the ping target doesn't exist.
    • HTTP GET to endpoints used by Big Vendors for their own network connectivity checks.
      • Google: http://clients3.google.com/generate_204 - should have a 204 response code (and I see the checkers that use this also check for a response content length of 0.)
      • Microsoft: http://www.msftncsi.com/ncsi.txt - should have a 200 response and the response body should read Microsoft NCSI.