Lua:使用pcall

时间:2017-01-08 17:23:51

标签: parameters lua try-catch

我有一段Lua代码正在发送udp消息,这是有效的。但是我想让它更加错误证明。所以我输入了一个错误的DNS名称来引发解决方案失败。我真的不在乎该块中的失败,我只是希望能够优雅地处理错误。在其他语言中,我会使用try-catch。在这里,我理解pcall应该填补这个空白。所以我正在尝试使用pcall并尝试将buttonPin传递给sendMessageToServer()函数。

这种方法不起作用,没有捕获任何内容,整个节点崩溃:

if(pcall(sendMessageToServer, buttonPin))
then
    ledOn(ledGreen)
    print("Message sent.")
else
    ledOn(ledRed)
    print("Error: Message could not be sent.")
end

这种做法恰恰相反:它没有崩溃,看起来好像一切都好,所以pcall返回true:

if(pcall(function() sendMessageToServer(buttonPin) end))
then
    ledOn(ledGreen)
    print("Message sent.")
else
    ledOn(ledRed)
    print("Error: Message could not be sent.")
end

但它应该运行...如果我只是删除单词pcall,使该函数定期运行,则崩溃按预期发生。

祝你好运, 延

更新:完整代码并故意导致错误

require ("config")
require ("cryptography")

function armAllButtons()

    ledOff(ledGreen)
    ledOff(ledYellow)
    ledOff(ledRed)

    for i,v in ipairs(buttonPins)
    do
        --print(i,v)
        armButton(v)
    end
end

function armButton(buttonPin)
    print("Arming pin "..buttonPin.." for button presses.")

    gpio.mode(buttonPin,gpio.INT,gpio.FLOAT)
    gpio.trig(buttonPin, direction, function () notifyButtonPressed(buttonPin) end)

    print("Waiting for button press on "..buttonPin.."...")
end

function notifyButtonPressed(buttonPin)
    --print("Button pressed. Notifiying server at "..serverIp..":"..serverPort)

    -- show status
    ledOn(ledYellow)

    print("Button at pin "..buttonPin.." pressed.")

    ledOff(ledGreen)
    ledOff(ledYellow)
    ledOff(ledRed)

    -- show status
    --if(pcall(sendMessageToServer,buttonPin))
    if(sendMessageToServer(buttonPin))
    then
        ledOn(ledGreen)
        print("Message sent.")
    else
        ledOn(ledRed)
        print("Error: Message could not be sent.")
    end

    -- Rearm pin for interrupts
    armButton(buttonPin)
end

function sendMessageToServer(buttonPin)
    print("Notifying server at "..serverIp..":"..serverPort)
    --TODO: Include some variable. The current code is vulnerable to replay attacks.

    conn = net.createConnection(net.UDP, 0)
    conn:connect(serverPort,serverIp)
    local msg = node.chipid()..";"..buttonPin..";ButtonPressed"
    local hash = getHashValue(msg..encryptionPassword)
    print("Sending "..msg.." with hash "..hash.." to server "..serverIp..":"..serverPort)
    conn:send(msg..';'..hash)
    conn:close()
    conn = nil
end

function ledOn(ledPin)
    gpio.write(ledPin,gpio.HIGH)
end

function ledOff(ledPin) 
    gpio.write(ledPin,gpio.LOW)
end


armAllButtons()

不使用pcall时出错:

dofile("button.lua")
Arming pin 5 for button presses.
Waiting for button press on 5...
Arming pin 6 for button presses.
Waiting for button press on 6...
> Button at pin 5 pressed.
Notifying server at <incorrectDnsEntry>:36740
Sending 14695197;5;ButtonPressed with hash <someHashValue> to server <incorrectDnsEntry>:36740
Error: Message could not be sent.
Arming pin 5 for button presses.
Waiting for button press on 5...
DNS retry 1!
DNS retry 2!
DNS retry 3!
DNS retry 4!
DNS Fail!
?ˆÈ)ŠâF
‘ŽF
”Œ¦ú

NodeMCU 0.9.6 build 20150704  powered by Lua 5.1.4
Arming pin 5 for button presses.
Waiting for button press on 5...
Arming pin 6 for button presses.
Waiting for button press on 6...
IP unavaiable, Waiting...
> IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
IP unavaiable, Waiting...
Config done, IP is 192.168.x.x

使用pcall显示:

Config done, IP is 192.168.x.x
Button at pin 5 pressed.
Notifying server at <incorrectDnsEntry>:36740
Sending 14695197;5;ButtonPressed with hash <someHashValue> to server <incorrectDnsEntry>:36740
Message sent.
Arming pin 5 for button presses.
Waiting for button press on 5...

所以我没有手动发出错误信号。

1 个答案:

答案 0 :(得分:0)

你正在使用LuaSockets吗?您应该知道LuaSockets中的函数实际上不会引发错误。大多数函数,如udp send,在成功时返回1,在出现错误时返回nil + msg。如果要引发错误,则需要检查返回值并自行引发错误。一种非常常见的方法是将调用包装在一个断言中,如下所示:

assert(conn:send(msg..';'..hash))

如果你说它没有电脑就可以工作那么你实在在欺骗自己。看起来好像你这样做:

if(sendMessageToServer(buttonPin))
then
    ledOn(ledGreen)
    print("Message sent.")
else
    ledOn(ledRed)
    print("Error: Message could not be sent.")
end

以上代码将始终打印“错误:无法发送消息”。因为sendMessageToServer函数永远不会返回任何内容,在这种情况下,if条件将始终评估为false,并且无论您是否设法发送数据,都将在else块中结束。