Тайм-аут NodeMCU при использовании цикла while
У меня есть скрипт Lua, который отправляет мне электронное письмо через SMTP. Все отлично работает при загрузке в NodeMCU и говоря 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')
называется
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, который, по-видимому, прекрасно работает сам по себе?
2 ответа
Даже если это не может быть определенный ответ, я публикую его как таковой, так как комментарии слишком малы.
Во-первых, я предлагаю вам использовать сценарий, который я разместил для вашего предыдущего вопроса. Этот не обрабатывает настройку WiFi правильно. Вам нужно подождать в таймере, пока устройство не получит IP, прежде чем вы сможете продолжить. Помните, wifi.sta.config
не блокирует И так как он использует auto-connect=true
если не установлено явно, он попытается подключиться к точке доступа немедленно. Это также причина, почему wifi.sta.autoconnect(1)
это лишнее.
Я не понимаю код чтения АЦП, который вы разместили.
vp = 0
gpio.mode(vp, gpio.INPUT)
Мне кажется ненужным, потому что а) вы ничего не делаете с GPIO 0 и б) adc.read
поддерживает только 0.
Вместо того, чтобы использовать занятую петлю и постоянно кормить сторожевую собаку, что является очень плохим признаком, я предлагаю вам использовать интервальный таймер. Кроме того, я полагаю, вы не хотите разорвать петлю в первый раз, когда условие выполнено, и никогда не вернетесь? Итак, вам нужно оставаться в курсе и продолжать инициировать отправку почты, нет? Что-то вроде этого может быть (не проверено):
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)
Небольшая цитата из ссылки NodeMCU:
tmr.wdclr () Поток системного сторожевого таймера.
В общем, если вам когда-либо понадобится использовать эту функцию, вы делаете это неправильно.
Модель NodeMCU, управляемая событиями, означает, что нет необходимости сидеть в жестких циклах, ожидая, когда что-то произойдет. Скорее просто используйте обратные вызовы, чтобы получать уведомления, когда что-то происходит. При таком подходе никогда не нужно вручную подавать сторожевой таймер системы.
Пожалуйста, обратите внимание на вторую строку.:)
Не уверен, в чем ваша проблема, но почему вы вообще используете цикл while? Почему бы не использовать события таймера для регулярного опроса вашего АЦП?
Возможно, сторожевой таймер сработал, потому что ваш канал по какой-то причине опаздывает. В случае, если вы не кормите его вообще, прежде чем выйти из цикла.