使用While循环时NodeMCU超时 [英] NodeMCU timeout when using while loop

查看:107
本文介绍了使用While循环时NodeMCU超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Lua脚本,可以通过SMTP向自己发送电子邮件.上载到NodeMCU并说dofile("sendemail.lua")时,一切正常.

I have a Lua script that sends an email to myself via SMTP. Everything works fine when uploading to the NodeMCU and saying dofile("sendemail.lua").

-- sendmail.lua    

-- The email and password from the account you want to send emails from
    MY_EMAIL = "REDACTED"

EMAIL_PASSWORD = "REDACTED"

-- The SMTP server and port of your email provider.
-- If you don't know it google [my email provider] SMTP settings
SMTP_SERVER = "isp.smtp.server"
SMTP_PORT = 25

-- The account you want to send email to
mail_to = "REDACTED"

-- Your access point's SSID and password
SSID = "REDACTED"
SSID_PASSWORD = "REDACTED"

-- configure ESP as a station
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,SSID_PASSWORD)
wifi.sta.autoconnect(1)

email_subject = ""
email_body = ""
count = 0


local smtp_socket = nil -- will be used as socket to email server

-- The display() function will be used to print the SMTP server's response
function display(sck,response)
     print(response)
end

-- The do_next() function is used to send the SMTP commands to the SMTP server in the required sequence.
-- I was going to use socket callbacks but the code would not run callbacks after the first 3.
function do_next()
            if(count == 0)then
                count = count+1
                IP_ADDRESS = wifi.sta.getip()
                smtp_socket:send("HELO "..IP_ADDRESS.."\r\n")
            elseif(count==1) then
                count = count+1
                smtp_socket:send("AUTH LOGIN\r\n")
            elseif(count == 2) then
                count = count + 1
                smtp_socket:send("REDACTED".."\r\n")
            elseif(count == 3) then
                count = count + 1
                smtp_socket:send("REDACTED".."\r\n")
            elseif(count==4) then
                count = count+1
               smtp_socket:send("MAIL FROM:<" .. MY_EMAIL .. ">\r\n")
            elseif(count==5) then
                count = count+1
               smtp_socket:send("RCPT TO:<" .. mail_to ..">\r\n")
            elseif(count==6) then
                count = count+1
               smtp_socket:send("DATA\r\n")
            elseif(count==7) then
                count = count+1
                local message = string.gsub(
                "From: \"".. MY_EMAIL .."\"<"..MY_EMAIL..">\r\n" ..
                "To: \"".. mail_to .. "\"<".. mail_to..">\r\n"..
                "Subject: ".. email_subject .. "\r\n\r\n"  ..
                email_body,"\r\n.\r\n","")

                smtp_socket:send(message.."\r\n.\r\n")
            elseif(count==8) then
               count = count+1
                 tmr.stop(0)
                 smtp_socket:send("QUIT\r\n")
                 print("msg sent")
            else
               smtp_socket:close()
            end
            print(count)
end

-- The connectted() function is executed when the SMTP socket is connected to the SMTP server.
-- This function will create a timer to call the do_next function which will send the SMTP commands
-- in sequence, one by one, every 5000 seconds. 
-- You can change the time to be smaller if that works for you, I used 5000ms just because.
function connected(sck)
    tmr.alarm(0,5000,1,do_next)
end

-- @name send_email
-- @description Will initiated a socket connection to the SMTP server and trigger the connected() function
-- @param subject The email's subject
-- @param body The email's body
function send_email(subject,body)

     count = 0
     email_subject = subject
     email_body = body
     smtp_socket = net.createConnection(net.TCP,0)
     smtp_socket:on("connection",connected)
     smtp_socket:on("receive",display)
    smtp_socket:connect(SMTP_PORT, SMTP_SERVER)     
end
-- Send an email
send_email("ESP8266", "[[Hi, How are your IoT projects coming along? Best Wishes,ESP8266]]")

但是,我想使用一个循环来监视模拟输入值,并且仅在检测到某些模拟输入值时才发送电子邮件.因此,我在脚本的末尾,sendemail()函数定义之后和函数sendmail('subject', 'body')调用之前

However, I want to use a loop to monitor an analog input value and only send the email when certain analog input values are detected. Therefore, I added this code at the end of the script, after the sendemail() function definition and immediately before the function sendmail('subject', 'body') is called

vp = 0
gpio.mode(vp, gpio.INPUT)

while true do

    local v = adc.read(vp)
    if v < 840 or v > 870 then
        print(v)
        break
    end
    tmr.wdclr()
end
sendmail('subject', 'body')

while循环运行良好,可以无限期地等待来自模拟引脚的输入.找到该输入后,它将正确中断并调用sendmail函数.但是,一旦调用该函数,NodeMCU最终将重置.有时,它可以达到与服务器成功认证SMTP凭据的程度,有时,它甚至在关闭之前甚至无法生成HELO.可能是什么原因造成的?为什么sendmail.lua脚本能正常工作,然后突然添加一个似乎完全可以正常工作的小while循环,突然决定不工作?

The while loop works perfectly, waiting indefinitely for input from the analog pin. Once that input is found, it breaks correctly and calls the sendmail function. However, once that function is called, NodeMCU eventually resets. Sometimes it will get as far as successfully authenticating the SMTP credentials with the server, and sometimes it will not even make the HELO before it shuts down. What could possibly be causing this? Why would the sendmail.lua script work fine then suddenly decide not to work when adding this one small while loop that appears to work perfectly fine on its own?

推荐答案

即使它可能不是确定的答案,但由于注释输入太小,我还是这样张贴它.

Even if it may not be the definite answer I post it as such since the comment input is too small.

首先,建议您使用我为上一个问题发布的脚本.此人未正确处理WiFi设置.您需要等待计时器直到设备获得IP,然后才能继续.请记住, wifi.sta.config 是非阻塞的.并且由于未明确设置使用auto-connect=true,因此它将尝试立即连接到AP.这也是wifi.sta.autoconnect(1)多余的原因.

First, I suggest you use the script I posted for your previous question. This one isn't handling WiFi setup correctly. You need to wait in a timer until the device got an IP before you can continue. Remember, wifi.sta.config is non-blocking. And since it uses auto-connect=true if not set explicitly it'll try to connect to the AP immediately. That's also the reason why wifi.sta.autoconnect(1) is superfluous.

我不理解您发布的ADC阅读代码.

I don't understand the ADC reading code you posted.

vp = 0
gpio.mode(vp, gpio.INPUT)

对我来说似乎不必要,因为a)您不使用GPIO 0进行任何操作,并且b) adc.read 仅支持0.

Seems unnecessary to me because a) you don't do anything with GPIO 0 and b) adc.read only supports 0.

这是一个非常糟糕的信号,我建议您使用基于间隔的计时器.此外,我想您不想在第一次满足条件时就中断循环吗?因此,您需要保持循环并继续触发发送邮件,对吗?可能是这样(未经测试):

Rather than using a busy loop and constantly feeding the watch dog, which is a very bad sign, I suggest you use an interval based timer. Furthermore, I guess you don't wanna break the loop the first time the condition is met and never come back? So, you need to stay in the loop and keep triggering send mail, no? Something like this maybe (untested):

tmr.alarm(0, 200, tmr.ALARM_AUTO, function()
  local v = adc.read(0)
  if v < 840 or v > 870 then
    node.task.post(function()
      send_email("ESP8266", "[[Hi, How are your IoT projects coming along? Best Wishes,ESP8266]]")
    end)
  end
end)

这篇关于使用While循环时NodeMCU超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆