From 36d42010c2dfd86ab5eed59b4a3a665c8e4a2950 Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Wed, 11 Mar 2015 08:32:00 -0500 Subject: [PATCH 1/9] Added IMAP read email example. The example is working but the output sections are not 100% correct. Parsing the output and waiting for OK message from server is needed. --- lua_examples/email/read_email_imap.lua | 88 ++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 lua_examples/email/read_email_imap.lua diff --git a/lua_examples/email/read_email_imap.lua b/lua_examples/email/read_email_imap.lua new file mode 100644 index 00000000..fe96ed4a --- /dev/null +++ b/lua_examples/email/read_email_imap.lua @@ -0,0 +1,88 @@ +--- +-- @author Miguel (AllAboutEE.com) +-- @description Reads email via IMAP + +-- this could be your email (and it is in most cases even in you have a "username") +local IMAP_USERNAME = "myemail@xxx.rr.com" +local IMAP_PASSWORD = "mypassword" + +local IMAP_SERVER = "mail.twc.com" +local IMAP_PORT = "143" +local IMAP_TAG = "t1" + +local SSID = "ssid" +local SSID_PASSWORD = "password" + +wifi.setmode(wifi.STATION) +wifi.sta.config(SSID,SSID_PASSWORD) +wifi.sta.autoconnect(1) + + +function print_logout(sck,logout_reply) + print("=========== LOGOUT REPLY ==========\r\n") + print(logout_reply) +end + +function logout(sck) + print("Logging out...\r\n") + sck:on("receive",print_logout) + sck:send(IMAP_TAG .. " LOGOUT\r\n") +end + +function print_body(sck,email_body) + print("========== EMAIL BODY =========== \r\n") + print(email_body) + print("\r\n") + logout(sck) +end + +function fetch_body(sck) + print("\r\nFetching first mail body...\r\n") + sck:on("receive",print_body) + sck:send(IMAP_TAG .. " FETCH 1 BODY[TEXT]\r\n") +end + + +function print_header(sck, email_header) + print("============== EMAIL HEADERS ==========\r\n") + print(email_header) -- prints the email headers + print("\r\n") + fetch_body(sck) +end + +function fetch_header(sck) + print("\r\nFetching first mail headers...\r\n") + sck:on("receive",print_header) + sck:send(IMAP_TAG .. " FETCH 1 BODY[HEADER]\r\n") +end + +function print_login(sck,login_reply) + print("========== LOGIN REPLY ==========\r\n") + print(login_reply) + select(sck,"INBOX") + +end + +function print_select(sck,response) + print(response) + fetch_header(sck) +end + +function select(sck,mailbox) + print("Selecting inbox...\r\n") + sck:on("receive",print_select) + sck:send(IMAP_TAG .. " SELECT "..mailbox.."\r\n") +end + + + +function login(sck) + print("Logging in...\r\n") + sck:on("receive", print_login) + sck:send(IMAP_TAG .. " LOGIN " .. IMAP_USERNAME .. " ".. IMAP_PASSWORD.."\r\n") +end + + +local socket = net.createConnection(net.TCP,0) +socket:on("connection",login) +socket:connect(IMAP_PORT,IMAP_SERVER) From 56aa416535ab2b59a4dd520cb3679965f2e88300 Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Thu, 12 Mar 2015 01:16:02 -0500 Subject: [PATCH 2/9] Added imap lua module and updated read_email_imap.lua example to use module. There is a bug where Examine is not sent sometimes. --- lua_examples/email/read_email_imap.lua | 119 +++++++++++-------------- lua_modules/email/imap.lua | 79 ++++++++++++++++ 2 files changed, 130 insertions(+), 68 deletions(-) create mode 100644 lua_modules/email/imap.lua diff --git a/lua_examples/email/read_email_imap.lua b/lua_examples/email/read_email_imap.lua index fe96ed4a..bbd22b6b 100644 --- a/lua_examples/email/read_email_imap.lua +++ b/lua_examples/email/read_email_imap.lua @@ -3,86 +3,69 @@ -- @description Reads email via IMAP -- this could be your email (and it is in most cases even in you have a "username") -local IMAP_USERNAME = "myemail@xxx.rr.com" -local IMAP_PASSWORD = "mypassword" +require("imap") -local IMAP_SERVER = "mail.twc.com" +local IMAP_USERNAME = "myemail@domain.com" +local IMAP_PASSWORD = "myemailpassword" + +local IMAP_SERVER = "imap.domain.com" local IMAP_PORT = "143" local IMAP_TAG = "t1" local SSID = "ssid" -local SSID_PASSWORD = "password" +local SSID_PASSWORD = "ssidpassword" + + +local count = 0 wifi.setmode(wifi.STATION) wifi.sta.config(SSID,SSID_PASSWORD) wifi.sta.autoconnect(1) +local imap_socket = net.createConnection(net.TCP,0) -function print_logout(sck,logout_reply) - print("=========== LOGOUT REPLY ==========\r\n") - print(logout_reply) + +function setup(sck) + imap.config(IMAP_USERNAME, + IMAP_PASSWORD, + IMAP_TAG, + sck) + + imap.login(imap_socket) end -function logout(sck) - print("Logging out...\r\n") - sck:on("receive",print_logout) - sck:send(IMAP_TAG .. " LOGOUT\r\n") +imap_socket:on("connection",setup) +imap_socket:connect(IMAP_PORT,IMAP_SERVER) + +function do_next() + + if(imap.receive_complete() == true) then + print("receive complete") + + if (count == 0) then + print("Examine:\r\n") + imap.examine(imap_socket,"INBOX") + count = count + 1 + elseif (count == 1) then + imap.fetch_header(imap_socket,1,"SUBJECT") + count = count + 1 + elseif (count == 2) then + imap.fetch_header(imap_socket,1,"FROM") + count = count + 1 + elseif (count == 3) then + imap.fetch_body_plain_text(imap_socket,1) + count = count + 1 + elseif (count == 4) then + imap.logout(imap_socket) + count = count + 1 + else + print("The body is: ".. imap.get_body()) + tmr.stop(0) + imap_socket:close() + collectgarbage() + end + end + end -function print_body(sck,email_body) - print("========== EMAIL BODY =========== \r\n") - print(email_body) - print("\r\n") - logout(sck) -end - -function fetch_body(sck) - print("\r\nFetching first mail body...\r\n") - sck:on("receive",print_body) - sck:send(IMAP_TAG .. " FETCH 1 BODY[TEXT]\r\n") -end - - -function print_header(sck, email_header) - print("============== EMAIL HEADERS ==========\r\n") - print(email_header) -- prints the email headers - print("\r\n") - fetch_body(sck) -end - -function fetch_header(sck) - print("\r\nFetching first mail headers...\r\n") - sck:on("receive",print_header) - sck:send(IMAP_TAG .. " FETCH 1 BODY[HEADER]\r\n") -end - -function print_login(sck,login_reply) - print("========== LOGIN REPLY ==========\r\n") - print(login_reply) - select(sck,"INBOX") - -end - -function print_select(sck,response) - print(response) - fetch_header(sck) -end - -function select(sck,mailbox) - print("Selecting inbox...\r\n") - sck:on("receive",print_select) - sck:send(IMAP_TAG .. " SELECT "..mailbox.."\r\n") -end - - - -function login(sck) - print("Logging in...\r\n") - sck:on("receive", print_login) - sck:send(IMAP_TAG .. " LOGIN " .. IMAP_USERNAME .. " ".. IMAP_PASSWORD.."\r\n") -end - - -local socket = net.createConnection(net.TCP,0) -socket:on("connection",login) -socket:connect(IMAP_PORT,IMAP_SERVER) +tmr.alarm(0,1000,1, do_next) diff --git a/lua_modules/email/imap.lua b/lua_modules/email/imap.lua new file mode 100644 index 00000000..589481e4 --- /dev/null +++ b/lua_modules/email/imap.lua @@ -0,0 +1,79 @@ +local moduleName = ... +local M = {} +_G[moduleName] = M + +local USERNAME = "" +local PASSWORD = "" + +local SERVER = "" +local PORT = "" +local TAG = "" + +local body = "" + + +local receive_complete = false + +function M.receive_complete() + return receive_complete +end + + +local function display(socket, response) + print(response) + if(string.match(response,'complete') ~= nil) then + receive_complete = true + end +end + +function M.config(username,password,tag,sk) + USERNAME = username + PASSWORD = password + TAG = tag +end + +function M.login(socket) + receive_complete = false + socket:send(TAG .. " LOGIN " .. USERNAME .. " " .. PASSWORD .. "\r\n") + socket:on("receive",display) +end + +function M.examine(socket,mailbox) + + receive_complete = false + socket:send(TAG .. " EXAMINE " .. mailbox .. "\r\n") + socket:on("receive",display) +end + +function M.fetch_header(socket,msg_number,field) + + receive_complete = false + socket:send(TAG .. " FETCH " .. msg_number .. " BODY[HEADER.FIELDS (" .. field .. ")]\r\n") + socket:on("receive",display) +end + +function M.get_body() + return body +end + + +local function set_body(socket,response) + print(response) + body = body .. response + if(string.match(response,'complete') ~= nil) then + receive_complete = true + end +end + +function M.fetch_body_plain_text(socket,msg_number) +receive_complete = false + body = "" + socket:send(TAG .. " FETCH " .. msg_number .. " BODY[1]\r\n") + socket:on("receive",set_body) +end + +function M.logout(socket) + receive_complete = false + socket:send(TAG .. " LOGOUT\r\n") + socket:on("receive",display) +end From 72f767445fec755566de1ea91d5689af94faec3e Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Thu, 12 Mar 2015 11:27:01 -0500 Subject: [PATCH 3/9] Working example of IMAP read email module. --- lua_examples/email/read_email_imap.lua | 94 ++++++++++---- lua_modules/email/imap.lua | 167 +++++++++++++++++++++---- 2 files changed, 217 insertions(+), 44 deletions(-) diff --git a/lua_examples/email/read_email_imap.lua b/lua_examples/email/read_email_imap.lua index bbd22b6b..02289aec 100644 --- a/lua_examples/email/read_email_imap.lua +++ b/lua_examples/email/read_email_imap.lua @@ -1,71 +1,119 @@ --- -- @author Miguel (AllAboutEE.com) --- @description Reads email via IMAP +-- @description This example will read the first email in your inbox using IMAP and +-- display it through serial. The email server must provided unecrypted access. The code +-- was tested with an AOL and Time Waraner cable email ccounts (GMail and other services who do +-- not support no SSL access will not work). --- this could be your email (and it is in most cases even in you have a "username") require("imap") -local IMAP_USERNAME = "myemail@domain.com" -local IMAP_PASSWORD = "myemailpassword" +local IMAP_USERNAME = "email@domain.com" +local IMAP_PASSWORD = "password" -local IMAP_SERVER = "imap.domain.com" +-- find out your unencrypted imap server and port +-- from your email provided i.e. google "[my email service] imap settings" for example +local IMAP_SERVER = "imap.service.com" local IMAP_PORT = "143" -local IMAP_TAG = "t1" + +local IMAP_TAG = "t1" -- You do not need to change this +local IMAP_DEBUG = false -- change to true if you would like to see the entire conversation between + -- the ESP8266 and IMAP server local SSID = "ssid" -local SSID_PASSWORD = "ssidpassword" +local SSID_PASSWORD = "password" -local count = 0 +local count = 0 -- we will send several IMAP commands/requests, this variable helps keep track of which one to send +-- configure the ESP8266 as a station wifi.setmode(wifi.STATION) wifi.sta.config(SSID,SSID_PASSWORD) wifi.sta.autoconnect(1) +-- create an unencrypted connection local imap_socket = net.createConnection(net.TCP,0) +--- +-- @name setup +-- @description A call back function used to begin reading email +-- upon sucessfull connection to the IMAP server function setup(sck) + -- Set the email user name and password, IMAP tag, and if debugging output is needed imap.config(IMAP_USERNAME, IMAP_PASSWORD, IMAP_TAG, - sck) + IMAP_DEBUG) - imap.login(imap_socket) + imap.login(sck) end -imap_socket:on("connection",setup) -imap_socket:connect(IMAP_PORT,IMAP_SERVER) +imap_socket:on("connection",setup) -- call setup() upon connection +imap_socket:connect(IMAP_PORT,IMAP_SERVER) -- connect to the IMAP server +local subject = "" +local from = "" +local message = "" + +--- +-- @name do_next +-- @description A call back function for a timer alarm used to check if the previous +-- IMAP command reply has been processed. If the IMAP reply has been processed +-- this function will call the next IMAP command function necessary to read the email function do_next() - if(imap.receive_complete() == true) then - print("receive complete") + -- Check if the IMAP reply was processed + if(imap.response_processed() == true) then + + -- The IMAP reply was processed if (count == 0) then - print("Examine:\r\n") + -- After logging in we need to select the email folder from which we wish to read + -- in this case the INBOX folder imap.examine(imap_socket,"INBOX") count = count + 1 elseif (count == 1) then - imap.fetch_header(imap_socket,1,"SUBJECT") + -- After examining/selecting the INBOX folder we can begin to retrieve emails. + imap.fetch_header(imap_socket,imap.get_most_recent_num(),"SUBJECT") -- Retrieve the SUBJECT of the first/newest email count = count + 1 elseif (count == 2) then - imap.fetch_header(imap_socket,1,"FROM") + subject = imap.get_header() -- store the SUBJECT response in subject + imap.fetch_header(imap_socket,imap.get_most_recent_num(),"FROM") -- Retrieve the FROM of the first/newest email count = count + 1 elseif (count == 3) then - imap.fetch_body_plain_text(imap_socket,1) + from = imap.get_header() -- store the FROM response in from + imap.fetch_body_plain_text(imap_socket,imap.get_most_recent_num()) -- Retrieve the BODY of the first/newest email count = count + 1 elseif (count == 4) then - imap.logout(imap_socket) + body = imap.get_body() -- store the BODY response in body + imap.logout(imap_socket) -- Logout of the email account count = count + 1 else - print("The body is: ".. imap.get_body()) - tmr.stop(0) - imap_socket:close() - collectgarbage() + -- display the email contents + + -- create patterns to strip away IMAP protocl text from actual message + pattern1 = "(\*.+\}\r\n)" -- to remove "* n command (BODY[n] {n}" + pattern2 = "(\r\n.+)" -- to remove ") t1 OK command completed" + + from = string.gsub(from,pattern1,"") + from = string.gsub(from,pattern2,"") + print(from) + + subject = string.gsub(subject,pattern1,"") + subject = string.gsub(subject,pattern2,"") + print(subject) + + body = string.gsub(body,pattern1,"") + body = string.gsub(body,pattern2,"") + print("Message: " .. body) + + tmr.stop(0) -- Stop the timer alarm + imap_socket:close() -- close the IMAP socket + collectgarbage() -- clean up end end end +-- A timer alarm is sued to check if an IMAP reply has been processed tmr.alarm(0,1000,1, do_next) diff --git a/lua_modules/email/imap.lua b/lua_modules/email/imap.lua index 589481e4..4b2031ab 100644 --- a/lua_modules/email/imap.lua +++ b/lua_modules/email/imap.lua @@ -1,3 +1,19 @@ +--- +-- IMPORTANT: run node.compile("imap.lua") after uploading this script +-- to create a compiled module. Then run file.remove("imap.lua") +-- @name imap +-- @description An IMAP 4rev1 module that can be used to read email. +-- Tested on NodeMCU 0.9.5 build 20150213. +-- @date March 12, 2015 +-- @author Miguel +-- GitHub: https://github.com/AllAboutEE +-- YouTube: https://www.youtube.com/user/AllAboutEE +-- Website: http://AllAboutEE.com +-- +-- Visit the following URLs to learn more about IMAP: +-- "How to test an IMAP server by using telnet" http://www.anta.net/misc/telnet-troubleshooting/imap.shtml +-- "RFC 2060 - Internet Message Access Protocol - Version 4rev1" http://www.faqs.org/rfcs/rfc2060.html +------------------------------------------------------------------------------------------------------------- local moduleName = ... local M = {} _G[moduleName] = M @@ -9,71 +25,180 @@ local SERVER = "" local PORT = "" local TAG = "" -local body = "" +local DEBUG = false + +local body = "" -- used to store an email's body / main text +local header = "" -- used to store an email's last requested header field e.g. SUBJECT, FROM, DATA etc. +local most_recent_num = 1 -- used to store the latest/newest email number/id -local receive_complete = false +local response_processed = false -- used to know if the last IMAP response has been processed -function M.receive_complete() - return receive_complete +--- +-- @name response_processed +-- @returns The response process status of the last IMAP command sent +function M.response_processed() + return response_processed end - +--- +-- @name display +-- @description A generic IMAP response processing function. +-- Can disply the IMAP response if DEBUG is set to true. +-- Sets the reponse processed variable to true when the string "complete" +-- is found in the IMAP reply/response local function display(socket, response) - print(response) - if(string.match(response,'complete') ~= nil) then - receive_complete = true + + -- If debuggins is enabled print the IMAP response + if(DEBUG) then + print(response) end + + -- Some IMAP responses are long enough that they will cause the display + -- function to be called several times. One thing is certain, IMAP will replay with + -- " OK complete" when it's done sending data back. + if(string.match(response,'complete') ~= nil) then + response_processed = true + end + end -function M.config(username,password,tag,sk) +--- +-- @name config +-- @description Initiates the IMAP settings +function M.config(username,password,tag,debug) USERNAME = username PASSWORD = password TAG = tag + DEBUG = debug end +--- +-- @name login +-- @descrpiton Logs into a new email session function M.login(socket) - receive_complete = false + response_processed = false -- we are sending a new command + -- which means that the response for it has not been processed socket:send(TAG .. " LOGIN " .. USERNAME .. " " .. PASSWORD .. "\r\n") socket:on("receive",display) end +--- +-- @name get_most_recent_num +-- @returns The most recent email number. Should only be called after examine() +function M.get_most_recent_num() + return most_recent_num +end + +--- +-- @name set_most_recent_num +-- @description Gets the most recent email number from the EXAMINE command. +-- i.e. if EXAMINE returns "* 4 EXISTS" this means that there are 4 emails, +-- so the latest/newest will be identified by the number 4 +local function set_most_recent_num(socket,response) + + if(DEBUG) then + print(response) + end + + local _, _, num = string.find(response,"([0-9]+) EXISTS(\.)") -- the _ and _ keep the index of the string found + -- but we don't care about that. + + if(num~=nil) then + most_recent_num = num + end + + if(string.match(response,'complete') ~= nil) then + response_processed = true + end +end + +--- +-- @name examine +-- @description IMAP examines the given mailbox/folder. Sends the IMAP EXAMINE command function M.examine(socket,mailbox) - receive_complete = false + response_processed = false socket:send(TAG .. " EXAMINE " .. mailbox .. "\r\n") - socket:on("receive",display) + socket:on("receive",set_most_recent_num) end +--- +-- @name get_header +-- @returns The last fetched header field +function M.get_header() + return header +end + +--- +-- @name set_header +-- @description Records the IMAP header field response in a variable +-- so that it may be read later +local function set_header(socket,response) + if(DEBUG) then + print(response) + end + + header = header .. response + if(string.match(response,'complete') ~= nil) then + response_processed = true + end +end + +--- +-- @name fetch_header +-- @description Fetches an emails header field e.g. SUBJECT, FROM, DATE +-- @param socket The IMAP socket to use +-- @param msg_number The email number to read e.g. 1 will read fetch the latest/newest email +-- @param field A header field such as SUBJECT, FROM, or DATE function M.fetch_header(socket,msg_number,field) - - receive_complete = false + header = "" -- we are getting a new header so clear this variable + response_processed = false socket:send(TAG .. " FETCH " .. msg_number .. " BODY[HEADER.FIELDS (" .. field .. ")]\r\n") - socket:on("receive",display) + socket:on("receive",set_header) end + +--- +-- @name get_body +-- @return The last email read's body function M.get_body() return body end - +--- +-- @name set_body +-- @description Records the IMAP body response in a variable +-- so that it may be read later local function set_body(socket,response) - print(response) + + if(DEBUG) then + print(response) + end + body = body .. response if(string.match(response,'complete') ~= nil) then - receive_complete = true + response_processed = true end end +--- +-- @name fetch_body_plain_text +-- @description Sends the IMAP command to fetch a plain text version of the email's body +-- @param socket The IMAP socket to use +-- @param msg_number The email number to obtain e.g. 1 will obtain the latest email function M.fetch_body_plain_text(socket,msg_number) -receive_complete = false - body = "" + response_processed = false + body = "" -- clear the body variable since we'll be fetching a new email socket:send(TAG .. " FETCH " .. msg_number .. " BODY[1]\r\n") socket:on("receive",set_body) end +--- +-- @name logout +-- @description Sends the IMAP command to logout of the email session function M.logout(socket) - receive_complete = false + response_processed = false socket:send(TAG .. " LOGOUT\r\n") socket:on("receive",display) end From 998f96a4d6b0b0a86eeca434d7a7875629628c59 Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Fri, 13 Mar 2015 14:39:14 -0500 Subject: [PATCH 4/9] Added base64 module needed to encode username and password. Added SMTP send email example. --- lua_examples/email/send_email_smtp.lua | 96 ++++++++++++++++++++++++++ lua_modules/base64/base64.lua | 41 +++++++++++ 2 files changed, 137 insertions(+) create mode 100644 lua_examples/email/send_email_smtp.lua create mode 100644 lua_modules/base64/base64.lua diff --git a/lua_examples/email/send_email_smtp.lua b/lua_examples/email/send_email_smtp.lua new file mode 100644 index 00000000..637cd638 --- /dev/null +++ b/lua_examples/email/send_email_smtp.lua @@ -0,0 +1,96 @@ +require("base64") + +local MY_EMAIL = "esp8266@domain.com" +local EMAIL_PASSWORD = "123456" + +local SMTP_SERVER = "smtp.server.com" +local SMTP_PORT = "587" + +local mail_to = "to_email@domain.com" + +local SSID = "ssid" +local SSID_PASSWORD = "password" + +wifi.setmode(wifi.STATION) +wifi.sta.config(SSID,SSID_PASSWORD) +wifi.sta.autoconnect(1) + +local email_subject = "" +local email_body = "" +local receive_processed = false +local count = 0 + +local smtp_socket = net.createConnection(net.TCP,0) + +function display(sck,response) + print(response) +end + +function do_next() + if(count == 0)then + count = count+1 + local 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(base64.enc(MY_EMAIL).."\r\n") + elseif(count == 3) then + count = count + 1 + smtp_socket:send(base64.enc(EMAIL_PASSWORD).."\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") + else + smtp_socket:close() + end +end + +function connected(sck) + tmr.alarm(0,5000,1,do_next) +end + +function send_email(subject,body) + email_subject = subject + email_body = body + smtp_socket:on("connection",connected) + smtp_socket:on("receive",display) + smtp_socket:connect(SMTP_PORT,SMTP_SERVER) +end + +send_email( + "ESP8266", +[[Hi, +How are your IoT projects coming along? +Best Wishes, +ESP8266]]) + + + + + + + + + diff --git a/lua_modules/base64/base64.lua b/lua_modules/base64/base64.lua new file mode 100644 index 00000000..e3523a31 --- /dev/null +++ b/lua_modules/base64/base64.lua @@ -0,0 +1,41 @@ +-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss +-- licensed under the terms of the LGPL2 + +local moduleName = ... +local M = {} +_G[moduleName] = M + +-- character table string +local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + +-- encoding +function M.enc(data) + return ((data:gsub('.', function(x) + local r,b='',x:byte() + for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end + return r; + end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x) + if (#x < 6) then return '' end + local c=0 + for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end + return b:sub(c+1,c+1) + end)..({ '', '==', '=' })[#data%3+1]) +end + +-- decoding +function M.dec(data) + data = string.gsub(data, '[^'..b..'=]', '') + return (data:gsub('.', function(x) + if (x == '=') then return '' end + local r,f='',(b:find(x)-1) + for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end + return r; + end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x) + if (#x ~= 8) then return '' end + local c=0 + for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(7-i) or 0) end + return string.char(c) + end)) +end + +return M From be4bb14e7c4e472565ce507ac412035903dd0fde Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Fri, 13 Mar 2015 20:51:19 -0500 Subject: [PATCH 5/9] Added comments to send_email_smtp and removed an unecessary variable. Fixed mispelling in comment in read_email_imap.lua --- lua_examples/email/read_email_imap.lua | 2 +- lua_examples/email/send_email_smtp.lua | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/lua_examples/email/read_email_imap.lua b/lua_examples/email/read_email_imap.lua index 02289aec..13aa7db6 100644 --- a/lua_examples/email/read_email_imap.lua +++ b/lua_examples/email/read_email_imap.lua @@ -2,7 +2,7 @@ -- @author Miguel (AllAboutEE.com) -- @description This example will read the first email in your inbox using IMAP and -- display it through serial. The email server must provided unecrypted access. The code --- was tested with an AOL and Time Waraner cable email ccounts (GMail and other services who do +-- was tested with an AOL and Time Warner cable email accounts (GMail and other services who do -- not support no SSL access will not work). require("imap") diff --git a/lua_examples/email/send_email_smtp.lua b/lua_examples/email/send_email_smtp.lua index 637cd638..1c79b6e5 100644 --- a/lua_examples/email/send_email_smtp.lua +++ b/lua_examples/email/send_email_smtp.lua @@ -1,31 +1,42 @@ require("base64") +-- The email and password from the account you want to send emails from local MY_EMAIL = "esp8266@domain.com" local EMAIL_PASSWORD = "123456" +-- The SMTP server and port of your email provider. +-- If you don't know it google [my email provider] SMTP settings local SMTP_SERVER = "smtp.server.com" local SMTP_PORT = "587" +-- The account you want to send email to local mail_to = "to_email@domain.com" +-- Your access point's SSID and password local SSID = "ssid" local SSID_PASSWORD = "password" +-- configure ESP as a station wifi.setmode(wifi.STATION) wifi.sta.config(SSID,SSID_PASSWORD) wifi.sta.autoconnect(1) +-- These are global variables. Don't change their values +-- they will be changed in the functions below local email_subject = "" local email_body = "" -local receive_processed = false local count = 0 +-- create a socket to the SMTP server local smtp_socket = net.createConnection(net.TCP,0) +-- 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 @@ -67,10 +78,18 @@ function do_next() end 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) email_subject = subject email_body = body @@ -79,6 +98,7 @@ function send_email(subject,body) smtp_socket:connect(SMTP_PORT,SMTP_SERVER) end +-- Send an email send_email( "ESP8266", [[Hi, From 5c84359b5c9abfb1b682aeef2efb57d080043b88 Mon Sep 17 00:00:00 2001 From: HuangRui Date: Mon, 16 Mar 2015 05:40:43 +0800 Subject: [PATCH 6/9] ROM flash size can changed with detected size, fixed #283. --- app/modules/node.c | 139 +++++++++++++++++++-------------------- app/platform/flash_api.c | 109 ++++++++++++++++++++++++------ app/platform/flash_api.h | 13 ++-- app/user/user_main.c | 14 +++- 4 files changed, 178 insertions(+), 97 deletions(-) diff --git a/app/modules/node.c b/app/modules/node.c index 7a3af5fd..caf2af42 100644 --- a/app/modules/node.c +++ b/app/modules/node.c @@ -29,7 +29,7 @@ static int node_restart( lua_State* L ) { system_restart(); - return 0; + return 0; } // Lua: dsleep( us, option ) @@ -56,7 +56,7 @@ static int node_deepsleep( lua_State* L ) else system_deep_sleep( us ); } - return 0; + return 0; } // Lua: dsleep_set_options @@ -80,14 +80,14 @@ static int node_info( lua_State* L ) lua_pushinteger(L, NODE_VERSION_REVISION); lua_pushinteger(L, system_get_chip_id()); // chip id lua_pushinteger(L, spi_flash_get_id()); // flash id - #if defined(FLASH_SAFE_API) +#if defined(FLASH_SAFE_API) lua_pushinteger(L, flash_safe_get_size_byte() / 1024); // flash size in KB - #else +#else lua_pushinteger(L, flash_rom_get_size_byte() / 1024); // flash size in KB - #endif // defined(FLASH_SAFE_API) +#endif // defined(FLASH_SAFE_API) lua_pushinteger(L, flash_rom_get_mode()); lua_pushinteger(L, flash_rom_get_speed()); - return 8; + return 8; } // Lua: chipid() @@ -95,7 +95,7 @@ static int node_chipid( lua_State* L ) { uint32_t id = system_get_chip_id(); lua_pushinteger(L, id); - return 1; + return 1; } // Lua: readvdd33() static int node_readvdd33( lua_State* L ) @@ -110,28 +110,23 @@ static int node_flashid( lua_State* L ) { uint32_t id = spi_flash_get_id(); lua_pushinteger( L, id ); - return 1; + return 1; } // Lua: flashsize() static int node_flashsize( lua_State* L ) { - //uint32_t sz = 0; - //if(lua_type(L, 1) == LUA_TNUMBER) - //{ - // sz = luaL_checkinteger(L, 1); - // if(sz > 0) - // { - // flash_set_size_byte(sz); - // } - //} + if (lua_type(L, 1) == LUA_TNUMBER) + { + flash_rom_set_size_byte(luaL_checkinteger(L, 1)); + } #if defined(FLASH_SAFE_API) uint32_t sz = flash_safe_get_size_byte(); #else uint32_t sz = flash_rom_get_size_byte(); #endif // defined(FLASH_SAFE_API) lua_pushinteger( L, sz ); - return 1; + return 1; } // Lua: heap() @@ -139,7 +134,7 @@ static int node_heap( lua_State* L ) { uint32_t sz = system_get_free_heap_size(); lua_pushinteger(L, sz); - return 1; + return 1; } static lua_State *gL = NULL; @@ -154,7 +149,7 @@ static int node_led( lua_State* L ) if ( lua_isnumber(L, 1) ) { low = lua_tointeger(L, 1); - if ( low < 0 ){ + if ( low < 0 ) { return luaL_error( L, "wrong arg type" ); } } else { @@ -163,7 +158,7 @@ static int node_led( lua_State* L ) if ( lua_isnumber(L, 2) ) { high = lua_tointeger(L, 2); - if ( high < 0 ){ + if ( high < 0 ) { return luaL_error( L, "wrong arg type" ); } } else { @@ -171,14 +166,14 @@ static int node_led( lua_State* L ) } led_high_count = (uint32_t)high / READLINE_INTERVAL; led_low_count = (uint32_t)low / READLINE_INTERVAL; - return 0; + return 0; } static int long_key_ref = LUA_NOREF; static int short_key_ref = LUA_NOREF; -void default_long_press(void *arg){ - if(led_high_count == 12 && led_low_count == 12){ +void default_long_press(void *arg) { + if (led_high_count == 12 && led_low_count == 12) { led_low_count = led_high_count = 6; } else { led_low_count = led_high_count = 12; @@ -188,32 +183,32 @@ void default_long_press(void *arg){ // NODE_DBG("default_long_press is called. hc: %d, lc: %d\n", led_high_count, led_low_count); } -void default_short_press(void *arg){ +void default_short_press(void *arg) { system_restart(); } -void key_long_press(void *arg){ +void key_long_press(void *arg) { NODE_DBG("key_long_press is called.\n"); - if(long_key_ref == LUA_NOREF){ + if (long_key_ref == LUA_NOREF) { default_long_press(arg); return; } - if(!gL) + if (!gL) return; lua_rawgeti(gL, LUA_REGISTRYINDEX, long_key_ref); lua_call(gL, 0, 0); } -void key_short_press(void *arg){ +void key_short_press(void *arg) { NODE_DBG("key_short_press is called.\n"); - if(short_key_ref == LUA_NOREF){ + if (short_key_ref == LUA_NOREF) { default_short_press(arg); return; } - if(!gL) + if (!gL) return; lua_rawgeti(gL, LUA_REGISTRYINDEX, short_key_ref); - lua_call(gL, 0, 0); + lua_call(gL, 0, 0); } // Lua: key(type, function) @@ -221,32 +216,32 @@ static int node_key( lua_State* L ) { int *ref = NULL; size_t sl; - + const char *str = luaL_checklstring( L, 1, &sl ); if (str == NULL) return luaL_error( L, "wrong arg type" ); - if(sl == 5 && c_strcmp(str, "short") == 0){ + if (sl == 5 && c_strcmp(str, "short") == 0) { ref = &short_key_ref; - }else if(sl == 4 && c_strcmp(str, "long") == 0){ + } else if (sl == 4 && c_strcmp(str, "long") == 0) { ref = &long_key_ref; - }else{ + } else { ref = &short_key_ref; } gL = L; // luaL_checkanyfunction(L, 2); - if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION){ + if (lua_type(L, 2) == LUA_TFUNCTION || lua_type(L, 2) == LUA_TLIGHTFUNCTION) { lua_pushvalue(L, 2); // copy argument (func) to the top of stack - if(*ref != LUA_NOREF) + if (*ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, *ref); *ref = luaL_ref(L, LUA_REGISTRYINDEX); } else { // unref the key press function - if(*ref != LUA_NOREF) + if (*ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, *ref); - *ref = LUA_NOREF; + *ref = LUA_NOREF; } - return 0; + return 0; } #endif @@ -256,15 +251,15 @@ extern void dojob(lua_Load *load); // Lua: input("string") static int node_input( lua_State* L ) { - size_t l=0; + size_t l = 0; const char *s = luaL_checklstring(L, 1, &l); if (s != NULL && l > 0 && l < LUA_MAXINPUT - 1) { lua_Load *load = &gLoad; - if(load->line_position == 0){ + if (load->line_position == 0) { c_memcpy(load->line, s, l); - load->line[l+1] = '\0'; - load->line_position = c_strlen(load->line)+1; + load->line[l + 1] = '\0'; + load->line_position = c_strlen(load->line) + 1; load->done = 1; NODE_DBG("Get command:\n"); NODE_DBG(load->line); // buggy here @@ -279,18 +274,18 @@ static int node_input( lua_State* L ) static int output_redir_ref = LUA_NOREF; static int serial_debug = 1; -void output_redirect(const char *str){ +void output_redirect(const char *str) { // if(c_strlen(str)>=TX_BUFF_SIZE){ // NODE_ERR("output too long.\n"); // return; // } - if(output_redir_ref == LUA_NOREF || !gL){ + if (output_redir_ref == LUA_NOREF || !gL) { uart0_sendStr(str); return; } - if(serial_debug!=0){ + if (serial_debug != 0) { uart0_sendStr(str); } @@ -304,15 +299,15 @@ static int node_output( lua_State* L ) { gL = L; // luaL_checkanyfunction(L, 1); - if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION){ + if (lua_type(L, 1) == LUA_TFUNCTION || lua_type(L, 1) == LUA_TLIGHTFUNCTION) { lua_pushvalue(L, 1); // copy argument (func) to the top of stack - if(output_redir_ref != LUA_NOREF) + if (output_redir_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref); output_redir_ref = luaL_ref(L, LUA_REGISTRYINDEX); } else { // unref the key press function - if(output_redir_ref != LUA_NOREF) + if (output_redir_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, output_redir_ref); - output_redir_ref = LUA_NOREF; + output_redir_ref = LUA_NOREF; serial_debug = 1; return 0; } @@ -320,26 +315,26 @@ static int node_output( lua_State* L ) if ( lua_isnumber(L, 2) ) { serial_debug = lua_tointeger(L, 2); - if(serial_debug!=0) + if (serial_debug != 0) serial_debug = 1; } else { serial_debug = 1; // default to 1 } - return 0; + return 0; } static int writer(lua_State* L, const void* p, size_t size, void* u) { UNUSED(L); int file_fd = *( (int *)u ); - if((FS_OPEN_OK - 1)==file_fd) + if ((FS_OPEN_OK - 1) == file_fd) return 1; - NODE_DBG("get fd:%d,size:%d\n",file_fd,size); - - if(size!=0 && (size!=fs_write(file_fd, (const char *)p, size)) ) + NODE_DBG("get fd:%d,size:%d\n", file_fd, size); + + if (size != 0 && (size != fs_write(file_fd, (const char *)p, size)) ) return 1; - NODE_DBG("write fd:%d,size:%d\n",file_fd,size); + NODE_DBG("write fd:%d,size:%d\n", file_fd, size); return 0; } @@ -351,45 +346,45 @@ static int node_compile( lua_State* L ) int file_fd = FS_OPEN_OK - 1; size_t len; const char *fname = luaL_checklstring( L, 1, &len ); - if( len > FS_NAME_MAX_LENGTH ) + if ( len > FS_NAME_MAX_LENGTH ) return luaL_error(L, "filename too long"); char output[FS_NAME_MAX_LENGTH]; c_strcpy(output, fname); // check here that filename end with ".lua". - if(len<4 || (c_strcmp( output+len-4,".lua")!=0) ) + if (len < 4 || (c_strcmp( output + len - 4, ".lua") != 0) ) return luaL_error(L, "not a .lua file"); - output[c_strlen(output)-2] = 'c'; - output[c_strlen(output)-1] = '\0'; + output[c_strlen(output) - 2] = 'c'; + output[c_strlen(output) - 1] = '\0'; NODE_DBG(output); NODE_DBG("\n"); - if (luaL_loadfsfile(L,fname)!=0){ - return luaL_error(L, lua_tostring(L,-1)); + if (luaL_loadfsfile(L, fname) != 0) { + return luaL_error(L, lua_tostring(L, -1)); } - f = toproto(L,-1); + f = toproto(L, -1); int stripping = 1; /* strip debug information? */ file_fd = fs_open(output, fs_mode2flag("w+")); - if(file_fd < FS_OPEN_OK) + if (file_fd < FS_OPEN_OK) { return luaL_error(L, "cannot open/write to file"); } lua_lock(L); - int result=luaU_dump(L,f,writer,&file_fd,stripping); + int result = luaU_dump(L, f, writer, &file_fd, stripping); lua_unlock(L); fs_flush(file_fd); fs_close(file_fd); file_fd = FS_OPEN_OK - 1; - if (result==LUA_ERR_CC_INTOVERFLOW){ + if (result == LUA_ERR_CC_INTOVERFLOW) { return luaL_error(L, "value too big or small for target integer type"); } - if (result==LUA_ERR_CC_NOTINTEGER){ + if (result == LUA_ERR_CC_NOTINTEGER) { return luaL_error(L, "target lua_Number is integral but fractional value found"); } @@ -399,7 +394,7 @@ static int node_compile( lua_State* L ) // Module function map #define MIN_OPT_LEVEL 2 #include "lrodefs.h" -const LUA_REG_TYPE node_map[] = +const LUA_REG_TYPE node_map[] = { { LSTRKEY( "restart" ), LFUNCVAL( node_restart ) }, { LSTRKEY( "dsleep" ), LFUNCVAL( node_deepsleep ) }, @@ -416,7 +411,7 @@ const LUA_REG_TYPE node_map[] = { LSTRKEY( "output" ), LFUNCVAL( node_output ) }, { LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) }, { LSTRKEY( "compile" ), LFUNCVAL( node_compile) }, -// Combined to dsleep(us, option) +// Combined to dsleep(us, option) // { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) }, #if LUA_OPTIMIZE_MEMORY > 0 diff --git a/app/platform/flash_api.c b/app/platform/flash_api.c index 6af6e31c..a648d91b 100644 --- a/app/platform/flash_api.c +++ b/app/platform/flash_api.c @@ -149,27 +149,21 @@ bool flash_rom_set_size_type(uint8_t size) // Dangerous, here are dinosaur infested!!!!! // Reboot required!!! // If you don't know what you're doing, your nodemcu may turn into stone ... -#if defined(FLASH_SAFE_API) + NODE_DBG("\nBEGIN SET FLASH HEADER\n"); uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR; - flash_safe_read(0, (uint32 *)data, sizeof(data)); - SPIFlashInfo *p_spi_flash_info = (SPIFlashInfo *)(data); - p_spi_flash_info->size = size; - flash_safe_erase_sector(0); - flash_safe_write(0, (uint32 *)data, sizeof(data)); - // TODO: CHECKSUM Firmware - //p_spi_flash_info = flash_rom_getinfo(); - //p_spi_flash_info->size = size; -#else - uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR; - spi_flash_read(0, (uint32 *)data, sizeof(data)); - SPIFlashInfo *p_spi_flash_info = (SPIFlashInfo *)(data); - p_spi_flash_info->size = size; - spi_flash_erase_sector(0); - spi_flash_write(0, (uint32 *)data, sizeof(data)); - // TODO: CHECKSUM Firmware - //p_spi_flash_info = flash_rom_getinfo(); - //p_spi_flash_info->size = size; -#endif // defined(FLASH_SAFE_API) + if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) + { + ((SPIFlashInfo *)(&data[0]))->size = size; + if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE)) + { + NODE_DBG("\nERASE SUCCESS\n"); + } + if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) + { + NODE_DBG("\nWRITE SUCCESS, %u\n", size); + } + } + NODE_DBG("\nEND SET FLASH HEADER\n"); return true; } @@ -207,6 +201,16 @@ bool flash_rom_set_size_byte(uint32_t size) flash_size = SIZE_32MBIT; flash_rom_set_size_type(flash_size); break; + case 8 * 1024 * 1024: + // 64Mbit, 8MByte + flash_size = SIZE_64MBIT; + flash_rom_set_size_type(flash_size); + break; + case 16 * 1024 * 1024: + // 128Mbit, 16MByte + flash_size = SIZE_128MBIT; + flash_rom_set_size_type(flash_size); + break; default: // Unknown flash size. result = false; @@ -272,6 +276,46 @@ uint32_t flash_rom_get_speed(void) return speed; } +bool flash_rom_set_speed(uint32_t speed) +{ + // Dangerous, here are dinosaur infested!!!!! + // Reboot required!!! + // If you don't know what you're doing, your nodemcu may turn into stone ... + NODE_DBG("\nBEGIN SET FLASH HEADER\n"); + uint8_t data[SPI_FLASH_SEC_SIZE] ICACHE_STORE_ATTR; + uint8_t speed_type = SPEED_40MHZ; + if (speed < 26700000) + { + speed_type = SPEED_20MHZ; + } + else if (speed < 40000000) + { + speed_type = SPEED_26MHZ; + } + else if (speed < 80000000) + { + speed_type = SPEED_40MHZ; + } + else if (speed >= 80000000) + { + speed_type = SPEED_80MHZ; + } + if (SPI_FLASH_RESULT_OK == spi_flash_read(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) + { + ((SPIFlashInfo *)(&data[0]))->speed = speed_type; + if (SPI_FLASH_RESULT_OK == spi_flash_erase_sector(0 * SPI_FLASH_SEC_SIZE)) + { + NODE_DBG("\nERASE SUCCESS\n"); + } + if (SPI_FLASH_RESULT_OK == spi_flash_write(0, (uint32 *)data, SPI_FLASH_SEC_SIZE)) + { + NODE_DBG("\nWRITE SUCCESS, %u\n", speed_type); + } + } + NODE_DBG("\nEND SET FLASH HEADER\n"); + return true; +} + bool flash_init_data_written(void) { // FLASH SEC - 4 @@ -356,3 +400,28 @@ uint8_t byte_of_aligned_array(const uint8_t *aligned_array, uint32_t index) uint8_t *p = (uint8_t *) (&v); return p[ (index % 4) ]; } + +// uint8_t flash_rom_get_checksum(void) +// { +// // SPIFlashInfo spi_flash_info ICACHE_STORE_ATTR = flash_rom_getinfo(); +// // uint32_t address = sizeof(spi_flash_info) + spi_flash_info.segment_size; +// // uint32_t address_aligned_4bytes = (address + 3) & 0xFFFFFFFC; +// // uint8_t buffer[64] = {0}; +// // spi_flash_read(address, (uint32 *) buffer, 64); +// // uint8_t i = 0; +// // c_printf("\nBEGIN DUMP\n"); +// // for (i = 0; i < 64; i++) +// // { +// // c_printf("%02x," , buffer[i]); +// // } +// // i = (address + 0x10) & 0x10 - 1; +// // c_printf("\nSIZE:%d CHECK SUM:%02x\n", spi_flash_info.segment_size, buffer[i]); +// // c_printf("\nEND DUMP\n"); +// // return buffer[0]; +// return 0; +// } + +// uint8_t flash_rom_calc_checksum(void) +// { +// return 0; +// } \ No newline at end of file diff --git a/app/platform/flash_api.h b/app/platform/flash_api.h index f912be41..ff276a83 100644 --- a/app/platform/flash_api.h +++ b/app/platform/flash_api.h @@ -16,10 +16,10 @@ #define FLASH_SIZE_256KBYTE (FLASH_SIZE_2MBIT / 8) #define FLASH_SIZE_512KBYTE (FLASH_SIZE_4MBIT / 8) -#define FLASH_SIZE_1MBYTE (FLASH_SIZE_8MBIT / 8) +#define FLASH_SIZE_1MBYTE (FLASH_SIZE_8MBIT / 8) #define FLASH_SIZE_2MBYTE (FLASH_SIZE_16MBIT / 8) #define FLASH_SIZE_4MBYTE (FLASH_SIZE_32MBIT / 8) -#define FLASH_SIZE_8MBYTE (FLASH_SIZE_64MBIT / 8) +#define FLASH_SIZE_8MBYTE (FLASH_SIZE_64MBIT / 8) #define FLASH_SIZE_16MBYTE (FLASH_SIZE_128MBIT/ 8) #define FLASH_SAFEMODE_ENTER() \ @@ -57,8 +57,8 @@ do { \ typedef struct { - uint8_t magic_e9; - uint8_t segments; + uint8_t header_magic; + uint8_t segment_count; enum { MODE_QIO = 0, @@ -83,6 +83,9 @@ typedef struct SIZE_64MBIT = 5, SIZE_128MBIT = 6, } size : 4; + uint32_t entry_point; + uint32_t memory_offset; + uint32_t segment_size; } ICACHE_STORE_TYPEDEF_ATTR SPIFlashInfo; uint32_t flash_detect_size_byte(void); @@ -104,5 +107,7 @@ bool flash_init_data_default(void); bool flash_init_data_blank(void); bool flash_self_destruct(void); uint8_t byte_of_aligned_array(const uint8_t* aligned_array, uint32_t index); +// uint8_t flash_rom_get_checksum(void); +// uint8_t flash_rom_calc_checksum(void); #endif // __FLASH_API_H__ diff --git a/app/user/user_main.c b/app/user/user_main.c index 7d470e2c..dee11754 100644 --- a/app/user/user_main.c +++ b/app/user/user_main.c @@ -60,7 +60,19 @@ void nodemcu_init(void) NODE_DBG("Can not init platform for modules.\n"); return; } - + +#if defined(FLASH_SAFE_API) + if( flash_safe_get_size_byte() != flash_rom_get_size_byte()) { + NODE_ERR("Self adjust flash size.\n"); + // Fit hardware real flash size. + flash_rom_set_size_byte(flash_safe_get_size_byte()); + // Flash init data at FLASHSIZE - 0x04000 Byte. + flash_init_data_default(); + // Flash blank data at FLASHSIZE - 0x02000 Byte. + flash_init_data_blank(); + } +#endif // defined(FLASH_SAFE_API) + if( !flash_init_data_written() ){ NODE_ERR("Restore init data.\n"); // Flash init data at FLASHSIZE - 0x04000 Byte. From 0144e40cf004f51dac69fe1c436a945584e71f8c Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Mon, 16 Mar 2015 00:39:29 -0500 Subject: [PATCH 7/9] Added comments and links to learn more about SMTP. --- lua_examples/email/send_email_smtp.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lua_examples/email/send_email_smtp.lua b/lua_examples/email/send_email_smtp.lua index 1c79b6e5..597a5f87 100644 --- a/lua_examples/email/send_email_smtp.lua +++ b/lua_examples/email/send_email_smtp.lua @@ -1,3 +1,13 @@ +--- +-- @description a basic SMTP email example. You must use an account which can provide unencrypted authenticated access. +-- This example was tested with an AOL and Time Warner email accounts. GMail does not offer unecrypted authenticated access. +-- To obtain your email's SMTP server and port simply Google it e.g. [my email domain] SMTP settings +-- For example for timewarner you'll get to this page http://www.timewarnercable.com/en/support/faqs/faqs-internet/e-mailacco/incoming-outgoing-server-addresses.html +-- To Learn more about SMTP email visit: +-- SMTP Commands Reference - http://www.samlogic.net/articles/smtp-commands-reference.htm +-- See "SMTP transport example" in this page http://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol +-- @author Miguel + require("base64") -- The email and password from the account you want to send emails from From 6c092e42ed99473cfb574f1c1caddc5549cbb2e6 Mon Sep 17 00:00:00 2001 From: AllAboutEE Date: Mon, 16 Mar 2015 04:17:19 -0500 Subject: [PATCH 8/9] Fixed bug where email text after CR and LF would not be read. Added example links, Fixed bug where send function could not be called more than once due to count variable. --- lua_examples/email/read_email_imap.lua | 5 +++-- lua_examples/email/send_email_smtp.lua | 7 +++++-- lua_modules/email/imap.lua | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lua_examples/email/read_email_imap.lua b/lua_examples/email/read_email_imap.lua index 13aa7db6..f64e5c31 100644 --- a/lua_examples/email/read_email_imap.lua +++ b/lua_examples/email/read_email_imap.lua @@ -1,4 +1,5 @@ --- +-- Working Example: https://www.youtube.com/watch?v=PDxTR_KJLhc -- @author Miguel (AllAboutEE.com) -- @description This example will read the first email in your inbox using IMAP and -- display it through serial. The email server must provided unecrypted access. The code @@ -16,7 +17,7 @@ local IMAP_SERVER = "imap.service.com" local IMAP_PORT = "143" local IMAP_TAG = "t1" -- You do not need to change this -local IMAP_DEBUG = false -- change to true if you would like to see the entire conversation between +local IMAP_DEBUG = true -- change to true if you would like to see the entire conversation between -- the ESP8266 and IMAP server local SSID = "ssid" @@ -93,7 +94,7 @@ function do_next() -- create patterns to strip away IMAP protocl text from actual message pattern1 = "(\*.+\}\r\n)" -- to remove "* n command (BODY[n] {n}" - pattern2 = "(\r\n.+)" -- to remove ") t1 OK command completed" + pattern2 = "(%)\r\n.+)" -- to remove ") t1 OK command completed" from = string.gsub(from,pattern1,"") from = string.gsub(from,pattern2,"") diff --git a/lua_examples/email/send_email_smtp.lua b/lua_examples/email/send_email_smtp.lua index 597a5f87..646b4ff6 100644 --- a/lua_examples/email/send_email_smtp.lua +++ b/lua_examples/email/send_email_smtp.lua @@ -1,4 +1,5 @@ --- +-- Working Example: https://www.youtube.com/watch?v=CcRbFIJ8aeU -- @description a basic SMTP email example. You must use an account which can provide unencrypted authenticated access. -- This example was tested with an AOL and Time Warner email accounts. GMail does not offer unecrypted authenticated access. -- To obtain your email's SMTP server and port simply Google it e.g. [my email domain] SMTP settings @@ -37,8 +38,8 @@ local email_subject = "" local email_body = "" local count = 0 --- create a socket to the SMTP server -local smtp_socket = net.createConnection(net.TCP,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) @@ -101,8 +102,10 @@ end -- @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) diff --git a/lua_modules/email/imap.lua b/lua_modules/email/imap.lua index 4b2031ab..e18e0d12 100644 --- a/lua_modules/email/imap.lua +++ b/lua_modules/email/imap.lua @@ -1,4 +1,5 @@ --- +-- Working Example: https://www.youtube.com/watch?v=PDxTR_KJLhc -- IMPORTANT: run node.compile("imap.lua") after uploading this script -- to create a compiled module. Then run file.remove("imap.lua") -- @name imap From b648e9a8db9baece822df0acd33b3f6e452b49df Mon Sep 17 00:00:00 2001 From: Markus Gritsch Date: Tue, 17 Mar 2015 10:23:45 +0100 Subject: [PATCH 9/9] Added node.setcpufreq(mhz) function. This function allows setting the CPU frequency to node.CPU80MHZ or node.CPU160MHZ. --- app/modules/node.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/app/modules/node.c b/app/modules/node.c index caf2af42..53d59ae0 100644 --- a/app/modules/node.c +++ b/app/modules/node.c @@ -25,6 +25,9 @@ #include "flash_fs.h" #include "user_version.h" +#define CPU80MHZ 80 +#define CPU160MHZ 160 + // Lua: restart() static int node_restart( lua_State* L ) { @@ -391,6 +394,24 @@ static int node_compile( lua_State* L ) return 0; } +// Lua: setcpufreq(mhz) +// mhz is either CPU80MHZ od CPU160MHZ +static int node_setcpufreq(lua_State* L) +{ + // http://www.esp8266.com/viewtopic.php?f=21&t=1369 + uint32_t new_freq = luaL_checkinteger(L, 1); + if (new_freq == CPU160MHZ){ + REG_SET_BIT(0x3ff00014, BIT(0)); + os_update_cpu_frequency(CPU160MHZ); + } else { + REG_CLR_BIT(0x3ff00014, BIT(0)); + os_update_cpu_frequency(CPU80MHZ); + } + new_freq = ets_get_cpu_frequency(); + lua_pushinteger(L, new_freq); + return 1; +} + // Module function map #define MIN_OPT_LEVEL 2 #include "lrodefs.h" @@ -411,6 +432,9 @@ const LUA_REG_TYPE node_map[] = { LSTRKEY( "output" ), LFUNCVAL( node_output ) }, { LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) }, { LSTRKEY( "compile" ), LFUNCVAL( node_compile) }, + { LSTRKEY( "CPU80MHZ" ), LNUMVAL( CPU80MHZ ) }, + { LSTRKEY( "CPU160MHZ" ), LNUMVAL( CPU160MHZ ) }, + { LSTRKEY( "setcpufreq" ), LFUNCVAL( node_setcpufreq) }, // Combined to dsleep(us, option) // { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) }, #if LUA_OPTIMIZE_MEMORY > 0 @@ -428,5 +452,5 @@ LUALIB_API int luaopen_node( lua_State *L ) // Add constants return 1; -#endif // #if LUA_OPTIMIZE_MEMORY > 0 +#endif // #if LUA_OPTIMIZE_MEMORY > 0 }