Search code examples
arrayslualua-table

How can I use a table in LUA for pinging multiple devices and detecting change in variable status


I am trying to ping a number of IP address on a local network at defined intervals and then send a message only when a device connects. I have managed to get it to work for a single device, but when I add additional devices to the table the code fails. Many thanks in advance.

An earlier version without the table and just a single IP address works perfectly. But adding the table and the "for key,value loop" only works if a single entry is in the table.

local tble = {
    ["device name"] = "192.168.1.204"
}
for key,value in pairs(tble) do

statuscheckIP=os.execute("arping -f -w 3 " .. value)


if statuscheckIP  ~= lastcheckIP then
if statuscheckIP == 0 and lastcheckIP == 256 then
subject ="" ..key.. " , ( IP Address " ..value.. ") Connected"
message = "Connection Alert\nThe device named " ..key.. ", with the IP address " ..value.. " has just connected to the WiFi network"
  --send email notification
  luup.call_action("urn:upnp-org:serviceId:SmtpNotification1", "SendEmail", { Recipient_Name="SomeOne", Recipient_eMail="someone@somewhere.com", Subject= subject, Message=message }, 24)luup.call_action("urn:upnporg:serviceId:SmtpNotification1","ResetCount",{}, 24)
  else
  end
 end
end
lastcheckIP = statuscheckIP

Solution

  • The code you posted is valid. There are not many reasons why this would fail due to more entries in your table.

    os.execute Execute an operating system shell command. This is like the C system() function. The system dependent status code is returned.

    Running os.execute will start a arping and return an exitcode. Then you are comparing that statuscheckIP == 0 a lastcheckIP == 256. The if before is redundant. If true you are sending your message and continuing.

    After worked though all entries you are setting lastcheckIP to statusCheckIP and this is propably your error. It should be before the last if and inside your loop. But even then does not make sense if 0 is the only correct return code. If lastcheckIP is set to any other value your both if's will never go true again.

    Either your last line lastcheckIP = statuscheckIP is wrongly placed, lastcheckIP was never initialized to 256 or you should rethink your whole program.

    EDIT:

    After understanding the intention of the provided program, I've created a probably working example. This should show you, how to easily use tables in Lua as a structures. I was not able to test the following code.

    local WAIT_TIME = 10
    
    local STATUS_CODE_CONNECTED = 0
    local STATUS_CODE_NOT_CONNECT = 256 -- not sure about this (return code from arping for failure)
    
    local device_table = 
    {
        ["device_name1"] =
        {
            ip = "<ip address>",
            status_code = STATUS_CODE_NOT_CONNECT
        },
        ["device_name1"] =
        {
            ip = "<ip address>",
            status_code = STATUS_CODE_NOT_CONNECT
        } 
        -- , ...
    }
    
    while true do
        -- check for changed return codes
        for device_name, device in pairs(device_table) do
            local temp_status_code = os.execute("arping -f -w 3 " .. device.ip)
    
            -- status code changed
            if temp_status_code ~= device.status_code then
    
                -- device connected
                if temp_status_code == STATUS_CODE_CONNECTED then
                    local subject = "" .. device_name .. " , ( IP Address " .. device.ip .. ") Connected"
                    local message = "Connection Alert\nThe device named " .. device_name .. ", with the IP address " .. device.ip .. " has just connected to the WiFi network"
    
                    --send email notification
    
                    luup.call_action(
                        "urn:upnp-org:serviceId:SmtpNotification1", 
                        "SendEmail", 
                        { 
                            Recipient_Name = "SomeOne", 
                            Recipient_eMail = "someone@somewhere.com", 
                            Subject = subject, 
                            Message = message 
                        }, 24)
                    luup.call_action(
                        "urn:upnporg:serviceId:SmtpNotification1", 
                        "ResetCount",
                        { }, 24)
                end
    
                -- update last device status_code if changed
                device.status_code = temp_status_code
            end
        end
    
        os.execute("sleep " .. tonumber(WAIT_TIME)) -- wait some time for next check
    end
    

    If I've understand you wrongly and you either do not want to have this program run all the time or do not want to have all addresses in a table then you should ask again or somewhere else because that would be out off topic.