2017-01-08 74 views
2

我有一段Lua代碼發送一個udp消息,這是工作。但是,我想讓它更加錯誤的證明。所以我輸入了一個錯誤的DNS名稱來挑起解決失敗。我真的不在乎那個塊的失敗,我只是希望能夠優雅地處理這個錯誤。在其他語言中,我會使用try-catch。在這裏,我明白pcall應該填補這個空白。所以我正在嘗試使用pcall,並試圖將buttonPin傳遞給sendMessageToServer()函數。Lua:使用pcall

這種方法是行不通的,沒有被捉住,整個節點崩潰:

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,使定期的功能來看,隨着預期發生崩潰。

此致 延

UPDATE:完整代碼和故意造成錯誤

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... 

所以我不是手動發信號通知錯誤。

+0

如果您表現出足夠的敬意,至少可以正確鍵入語言名稱,您會得到更多回復。 Lua並不是一個首字母縮寫詞,將L字母大寫,就是這樣。 Lua中。請修復這個問題。 – warspyking

+0

您可以顯示堆棧跟蹤對於故意觸發的錯誤的樣子嗎?錯誤如何發出信號?你使用'error' /'lua_error'還是你的代碼使用某種「帶外」方式來表示lua不理解的錯誤? – greatwolf

+0

我已更新我的原始問題以包含更多代碼和錯誤消息。 – Jens

回答

0

你正在使用LuaSockets嗎?你應該知道LuaSockets中的函數實際上不會引發錯誤。大多數函數,如udp send,成功時返回1,出錯時返回nil + msg。如果你想提出一個錯誤,你需要檢查返回值並自己提出錯誤。這樣做的一個非常普遍的方式是包裹呼叫斷言,這樣的:

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

當你說,它的工作原理沒有PCALL那麼你實際上愚弄自己。這看起來好像你正在做的是這樣的:

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

上面的代碼將始終打印「錯誤:消息無法發送。」因爲sendMessageToServer函數永遠不會返回任何內容,在這種情況下if條件總是計算爲false,並且無論您是否設法發送數據,您都將在else塊中結束。