IoT_hobbyist
Published © GPL3+

Arduino - Set Email List via Web

Without hard code, a number of email addresses are set via web. Saved to EEPROM. Arduino sends the notification to these email on events.

IntermediateFull instructions provided914
Arduino - Set Email List via Web

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
PHPoC WiFi Shield 2 for Arduino
PHPoC WiFi Shield 2 for Arduino
It works with one of the following shields: - PHPoC WiFi Shield for Arduino - PHPoC Shield for Arduino - PHPoC WiFi Shield 2 for Arduino - PHPoC Shield 2 for Arduino
×1

Story

Read more

Code

Arduino Code

Arduino
#include "SPI.h"
#include "Phpoc.h"
#include <EEPROM.h>

#ifndef EOF
#define EOF (-1)
#endif

#define CMD_ARDUINO_DEL 0
#define CMD_ARDUINO_GET 1
#define CMD_ARDUINO_ADD 2
#define CMD_WEB_CLR		5
#define CMD_WEB_UPD		6

#define MAX_NUM_EMAIL	10

class EepromCSV
{
    public:
        void clear(void);
        int line(void);
        String readLine(int line);
        void writeLine(String lineStr);
};

EepromCSV EepromCSV;
PhpocServer webServer(80);

String emailArray[MAX_NUM_EMAIL];
int numEmail;

int lastState = 1;
unsigned long lastUpdateTime;

void setup() {
    Serial.begin(9600);
    while(!Serial)
        ;
    Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
    webServer.beginWebSocket("arduino");

    Serial.print("WebSocket server address : ");
    Serial.println(Phpoc.localIP());

	//EepromCSV.clear();
	eepromToEmailList(); // load email from EEPROM

	lastState = digitalRead(A0);
	lastUpdateTime = millis();
}

void loop() {
    checkEmailListUpdate(); // check whether there is any config command from Web or not.

	int currentState = digitalRead(A0);

	if((millis() - lastUpdateTime) > 1000) // 1 second 
	{
		if(lastState != currentState)
		{
			if (lastState == 1 && currentState == 0) 
			{ // if door is opened...
				for(int i = 0; i < numEmail; i++)
				{
					sendRelayGmail(emailArray[i]);
					delay(1000);
				}

				lastUpdateTime = millis();
			}
			else
			if(lastState == 0 && currentState == 1)
			{ // if door is closed...
				// Write codes in the same way
			}

			lastState = currentState;
		}
	}
}

void sendRelayGmail(String emailAddress)
{
	PhpocEmail email;
	char charEmailAddr[50];

    emailAddress.toCharArray(charEmailAddr, emailAddress.length() + 1);

	email.setOutgoingServer("smtp.gmail.com", 587);
	email.setOutgoingLogin("example@gmail.com", "example_password");

	email.setFrom("example@gmail.com", "From Arduino Gmail");
	email.setTo(charEmailAddr, "To Whom It May Concern");

	email.setSubject(F("Door is opened. [#905]"));  // Mail Subject

	// Mail Contents
	email.beginMessage();
	email.println(F("#905"));
	email.println("");
	email.println(F("Door is opened."));
	email.endMessage();

	if (email.send() > 0)  // Send Email
		Serial.print(F("Your Mail has been sent successfully to "));
	else
		Serial.print(F("Your Mail is not sent to "));

	Serial.println(emailAddress);
}
void eepromToEmailList(void) {
	int lineCount = EepromCSV.line();

	if(lineCount > MAX_NUM_EMAIL)
		lineCount = MAX_NUM_EMAIL;

	for(int i = 0; i < lineCount; i++)
	{
		String line; 

		line = EepromCSV.readLine(i);
		emailArray[i] = line.substring(0, line.indexOf("\n"));
	}

	numEmail = lineCount;
}
void sendToWeb(String data) {
	char wbuf[50];

    data.toCharArray(wbuf, data.length() + 1);
    webServer.write(wbuf, data.length());
}
void checkEmailListUpdate(void) {
    // wait for a new client:
	PhpocClient client = webServer.available();

	if (client) 
	{
		// read a string that is terminated by a carriage return and a newline
		// characters:
		String data = client.readLine();

		if(data)
		{
			String email;
			int cmd;

            cmd = data.substring(0, 1).toInt();

			if(cmd == CMD_ARDUINO_GET)
			{
				int lineCount = EepromCSV.line();

				sendToWeb(String(CMD_WEB_CLR) + ",0\n"); /* tell web clear to load new email */

                for(int i = 0; i < lineCount; i++) 
				{
                    email = EepromCSV.readLine(i); /* read email from EEPROM one by one */
                    sendToWeb(String(CMD_WEB_UPD) + "," + email + "\n"); /* send email to Web */
                }
            }
			else
			if(cmd == CMD_ARDUINO_DEL) 
			{
				email = data.substring(2, data.indexOf("\r\n"));

				EepromCSV.clear(); /* clear to update new email */

				for(int i = 0; i < numEmail; i++)
				{
					if(!emailArray[i].equals(email)) 
						EepromCSV.writeLine( emailArray[i]); /* write email to EEPROM */
				}

				eepromToEmailList(); /* reload email from EEPROM */
            }
            else
			if(cmd == CMD_ARDUINO_ADD)
			{
				email = data.substring(2, data.lastIndexOf("\r\n"));

				if(email.length())
				{
					EepromCSV.writeLine(email); /* write email to EEPROM */
					eepromToEmailList(); /* reload email from EEPROM */
				}
            }
        }
    }
}

void EepromCSV::clear(void) {
	EEPROM.write(0, EOF);
	Serial.println(F("EepromCSV::clear"));
}
int EepromCSV::line(void) {
	int lineCount   = 0;
	int address     = 0;
	char value;

	while(1) {
		value = EEPROM.read(address++);

		if(value == '\n')
			lineCount++;
		else if(value == EOF)
			return lineCount;
	}
}
String EepromCSV::readLine(int line) {
	String retStr   = "";
	char value;
	int lineIndx    = 0;
	int address     = 0;

	while(lineIndx < line) {
		value = EEPROM.read(address++);
		if(value == '\n')
			lineIndx++;
		else if (value == EOF) {
			return "";
		}
	}

	while(1) {
		value = EEPROM.read(address++);

		if(value == '\n' || value == EOF)
		{
			Serial.print(F("EepromCSV::readLine:"));
			Serial.println(retStr);

			return retStr;
		}
		else
			retStr += value;
	}
}
void EepromCSV::writeLine(String lineStr) { /* add new line at the end of CSV file*/
	int address, length;

	address	= 0;
	length	= lineStr.length();

	while((char)EEPROM.read(address++) != EOF)
		;
	address--;

	for(int i = 0; i < length; i++)
		EEPROM.write(address++, lineStr.charAt(i));

	EEPROM.write(address++, '\n');
	EEPROM.write(address, EOF);

	Serial.print(F("EepromCSV::writeLine:"));
	Serial.println(lineStr);
}

Web Interface

PHP
<!DOCTYPE html>
<html>
<head>
<title>Arduino - Configure via Web</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<meta charset="utf-8">
<style>
body { text-align: center; font-size: 100%; font-family: Roboto;}
#header { background-color: #00979d; color: white; padding: 5px; margin-bottom: 15px}
h2 { font-weight: bold; font-size: 120%; }
table th { font-weight: bold; font-size: 120%; border-bottom: 8px solid #00979d; }
table td { font-weight: bold; font-size: 120%; height: 40px; }
select, input { font-size: 100%; font-family: Roboto;}
.button { border-top: 10px solid white; font-size:130%; background-color: red; color:white;}

</style>
<script>
var CMD_ARDUINO_DEL	= 0;
var CMD_ARDUINO_GET	= 1;
var CMD_ARDUINO_ADD	= 2;
var CMD_WEB_CLR		= 5;
var CMD_WEB_UPD		= 6;
var dayLookupTable = ["", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
var email_list = new Array();
var ws = null;
var buffer = "";

function init() {
	if(ws == null) {
		var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
		if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "[")) {
			// network resource identifier to UNC path name conversion
			ws_host_addr = ws_host_addr.replace(/[\[\]]/g, '');
			ws_host_addr = ws_host_addr.replace(/:/g, "-");
			ws_host_addr += ".ipv6-literal.net";
		}
		
		ws = new WebSocket("ws://" + ws_host_addr + "/arduino", "text.phpoc");
		ws.onopen = ws_onopen;
		ws.onclose = ws_onclose;
		ws.onmessage = ws_onmessage;
	}
	else
		ws.close();
}
function ws_onopen() {
	setTimeout(function() {
		ws.send(CMD_ARDUINO_GET + ",0\r\n");
	}, 100);
}
function ws_onclose() {
	ws.onopen = null;
	ws.onclose = null;
	ws.onmessage = null;
	ws = null;

	alert("Not connected to Arduino!");
}
function ws_onmessage(e_msg) {
	e_msg = e_msg || window.event; // MessageEvent
	
	buffer += e_msg.data;
	buffer = buffer.replace(/\r\n/g, "\n");
	buffer = buffer.replace(/\r/g, "\n");

	console.log(buffer);
	while(buffer.indexOf("\n") == 0)
		buffer = buffer.substr(1);
	
	while(buffer.indexOf("\n") >= 0) { // because multiple update data may come at the same time
		var data = buffer.substr(0, buffer.indexOf("\n"));
		buffer = buffer.substr(buffer.indexOf("\n") + 1);
		
		var arr = data.split(",");
		var cmd = parseInt(arr[0]);
		
		if(cmd == CMD_WEB_CLR) {
			email_list = new Array();
			
			var emailTable = document.getElementById("emailTable");
			while( emailTable.rows.length > 2)
				emailTable.deleteRow(1);
		}
		else if(cmd == CMD_WEB_UPD) {
			var email = arr[1];
			
			email_list.push(email);
			
			var emailTable = document.getElementById("emailTable");
			var numRow = emailTable.rows.length;
			var newRow = emailTable.insertRow(numRow - 1);
			newRow.insertCell().innerHTML = email;
			newRow.insertCell().innerHTML = '<span style="color:red;" onclick="deleteEmail(this)">delete</span>';

			newRow.cells[0].style.paddingRight="50px"
			newRow.cells[0].style.textAlign = "right";
			newRow.style.color = "#1E90FF";
		}
	}
}
function deleteEmail(event) {
	var rowIndex = event.parentElement.parentElement.rowIndex;
	document.getElementById("emailTable").deleteRow(rowIndex);

	var email = email_list[rowIndex - 1];
	email_list.splice(rowIndex - 1, 1);
	
	if(ws == null)
		alert("Not connected to Arduino!");
	else
		ws.send(CMD_ARDUINO_DEL + "," + email + "\r\n");
}
function addEmail(event) {
	var emailTable = document.getElementById("emailTable");
	var rowIndex = event.parentElement.parentElement.rowIndex;
	var row  = emailTable.rows[rowIndex];
	var email = row.cells[0].childNodes[0].value;

	if(!email)
		return;

	row.cells[0].innerHTML = email;
	row.cells[1].innerHTML = '<span style="font-size:120%; color:red;" onclick="deleteEmail(this)">delete</span>';

	row.cells[0].style.paddingRight="50px"
	row.cells[0].style.textAlign = "right";
	row.style.color = "#1E90FF";

	email_list.push(email);

	if(ws == null)
		alert("Not connected to Arduino!");
	else
		ws.send(CMD_ARDUINO_ADD + "," + email + "\r\n");
}
function newEmail() {
	var emailTable = document.getElementById("emailTable");
	var numRow = emailTable.rows.length;
	var newRow = emailTable.insertRow(numRow - 1);
	var cell0 = newRow.insertCell();
	var cell1 = newRow.insertCell();

	cell0.innerHTML = '<input type="email" name="email" style="border-color: red; width:80%">';
	cell1.innerHTML = '<span style="color:red;" onclick="addEmail(this)">add</span>';
}

window.onload = init;
</script>
</head>
<body>
<div id="header">
<span style="font-size:150%; font-weight: bold;">ARDUINO - EMAIL LIST</span><br>
<span style="font-size:130%; font-weight: normal;">Web To EEPROM</span>
</div>
<table id="emailTable"  style="width:100%; table-layout:fixed;">
	<tr>
		<th>EMAIL ADDRESS</th>
		<th width="30%">ADD / DELETE</th>
	</tr>
	<tr>
		<td class="button" colspan="2" onclick="newEmail(this)">NEW</td>
	</tr>
</table>
<br>
<h2>
</h2>
</body>
</html>

Credits

IoT_hobbyist
4 projects • 28 followers

Comments