Introduction: Electric Imp MailBox Notifications

I wanted to get into the IoT thing for a while. I was hesitating between the Imp and the SparkCore and finally I went for the Imp. So far the market does not have plenty of devices like them.

A cool and easy project to start with was to monitor my mailbox.

I bought my electric Imp from my local dealer arobose at a very good price and also the April board.

Here is the parts list:

- Electric imp from arobose

- April Board from arobose

- Nokia battery

- Microswitch from ebay

- Led + resistor

- Tempsensor TMP36

- Random cables and connectors

- Hard Drive Magnets

- Hair gel Box

- Time (priceless!!!)

Step 1: Step 1 : First Contact With the Imp.

After I had all my components, i hooked them up and tried to blink a LED.

If you follow the tutorials online it is more than easy.

For me the online IDE is not the best ever, but it does the job, and you can also access remotely your imp and update your code on the fly unless you are using deepSleep... In that case you cannot access it (normal)!

After the first tests, I connected a 3v7 1000mah battery from an old nokia that should last for a while as the specs for sleep mode power consumption is only 6uA... We'll see what happens in real life!

Step 2: Step 2: the MailBox !

Depending on the part of the world you are living mailboxes can be pretty different ;-)

For me in France, we are used to have mailboxes with a main door and a small one on it just for letters.

Anyway, so far I'll be monitoring the main one for "big packets".

I was hesitating between reed switch and normal switch but finally I decided to use the good old switches!

Maybe after I'll use a reed switch for the small door monitoring.

Basically it is a normally closed switch, then as long as the lock of the door is closed I have the switch open.

For debug I have attached it to an hard-drive magnet to easily place/remove it.

I did the same with the box where I have placed the imp, a magnet just below the cover allows me to fix it under my mailbox!

Step 3: Step 3: the Code

As we have seen all the mechanical issues ;-) let's dive into the software.

To test it a little bit more, I have added a temp sensor (tmp36) to monitor temperature every 15 min and report it on a live graph using Xively.

In a few words, device is in sleep mode all the time, every 15 min it wakes up, sends temperature to Xively, sends an email and goes to sleep again.

If I have mail, it wakes up due to the external interrupt (pin 1 only!), it sends me an email and an SMS.

An led is there just for debug purpose.

In every messages I received from it I have also added battery monitoring.

Source Code:

Agent:

// TempBug Example Agent Code<br>
/* GLOBALS and CONSTANTS -----------------------------------------------------*/
const XIVELY_API_KEY = "blablabla";
const XIVELY_FEED_ID = "blablabla";
const XIVELYCHANNEL = "temperature";
Xively <- {};  // this makes a 'namespace'
/* CLASS AND GLOBAL FUNCTION DEFINITIONS -------------------------------------*
/ Xively "library". See <a href="https://github.com/electricimp/reference/tree/master/webservices/xively" rel="nofollow"> https://github.com/electricimp/reference/tree/mas...</a>
class Xively.Client {
    ApiKey = null;
    triggers = [];
	constructor(apiKey) {
		this.ApiKey = apiKey;
	}
	/*****************************************
	 * method: PUT
	 * IN:
	 *   feed: a XivelyFeed we are pushing to
	 *   ApiKey: Your Xively API Key
	 * OUT:
	 *   HttpResponse object from Xively
	 *   200 and no body is success
	 *****************************************/
	function Put(feed){
		local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
		local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
		local request = http.put(url, headers, feed.ToJson());
		return request.sendsync();
	}
	/*****************************************
	 * method: GET
	 * IN:
	 *   feed: a XivelyFeed we fulling from
	 *   ApiKey: Your Xively API Key
	 * OUT:
	 *   An updated XivelyFeed object on success
	 *   null on failure
	 *****************************************/
	function Get(feed){
		local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
		local headers = { "X-ApiKey" : ApiKey, "User-Agent" : "xively-Imp-Lib/1.0" };
		local request = http.get(url, headers);
		local response = request.sendsync();
		if(response.statuscode != 200) {
			server.log("error sending message: " + response.body);
			return null;
		}
		local channel = http.jsondecode(response.body);
		for (local i = 0; i < channel.datastreams.len(); i++)
		{
			for (local j = 0; j < feed.Channels.len(); j++)
			{
				if (channel.datastreams[i].id == feed.Channels[j].id)
				{
					feed.Channels[j].current_value = channel.datastreams[i].current_value;
					break;
				}
			}
		}
		return feed;
	}
}
    
class Xively.Feed{
    FeedID = null;
    Channels = null;
    
    constructor(feedID, channels)
    {
        this.FeedID = feedID;
        this.Channels = channels;
    }
    
    function GetFeedID() { return FeedID; }
    function ToJson()
    {
        local json = "{ \"datastreams\": [";
        for (local i = 0; i < this.Channels.len(); i++)
        {
            json += this.Channels[i].ToJson();
            if (i < this.Channels.len() - 1) json += ",";
        }
        json += "] }";
        return json;
    }
}
class Xively.Channel {
    id = null;
    current_value = null;
    
    constructor(_id)
    {
        this.id = _id;
    }
    
    function Set(value) { 
    	this.current_value = value; 
    }
    
    function Get() { 
    	return this.current_value; 
    }
    
    function ToJson() { 
    	return http.jsonencode({id = this.id, current_value = this.current_value }); 
    }
}
function postToXively(data,id) {
    xivelyChannel <- Xively.Channel(XIVELYCHANNEL+id);
    xivelyChannel.Set(data);
    xivelyFeed <- Xively.Feed(XIVELY_FEED_ID, [xivelyChannel]);
    local resp = xivelyClient.Put(xivelyFeed);
    server.log("Posted to Xively: "+data+", got return code: "+resp.statuscode+", msg: "+resp.body);
}
/* REGISTER DEVICE CALLBACKS  ------------------------------------------------*/
device.on("data", function(datapoint) {
    postToXively(datapoint.temp, datapoint.id);
});
/* REGISTER HTTP HANDLER -----------------------------------------------------*
/ This agent does not need an HTTP handler
/* RUNTIME BEGINS HERE -------------------------------------------------------*/
server.log("TempBug Agent Running");
// instantiate our Xively client
xivelyClient <- Xively.Client(XIVELY_API_KEY);
xivelyChannel <- Xively.Channel("temperature");
function mailgun(subject, message)
{
  local from = "Mailbox@home.com";
  local to   = "titi@toto.com"
  local apikey = "key-blablbabla";
  local domain = "blablabla.mailgun.org";
  local request = http.post("https://api:" + apikey + "@api.mailgun.net/v2/" + domain + "/messages", {"Content-Type": "application/x-www-form-urlencoded"}, "from=" + from + "&to=" + to + "&subject=" + subject + "&text=" + message);
  local response = request.sendsync();
  server.log("Mailgun response: " + response.body);
}
function sendEmail (voltage,tmp)
{
    
mailgun("Electric Imp", "Monitoring \nTension Batterie "+voltage+" Température "+tmp);
//http.get("https://smsapi.free-mobile.fr/sendmsg?user=blablabla&pass=blablabla&msg=Vous%20Avez%20Du%20Courrier!%0D", {}).sendsync();
                  
}
function sendSMS (voltage,temp)
{
    
    
    
mailgun("Electric Imp", "Courrier Reçu! ;-) \n");
http.get("https://smsapi.free-mobile.fr/sendmsg?user=blablabla&pass=blablabla&msg=Y'a%20Du%20Courrier!%0D"+"Batt="+voltage+"V T="+temp+"°C", {}).sendsync();
                  
}
//device.on("SMS", sendSMS); 
device.on("mail", function(datapoint2) {
    sendEmail(datapoint2.voltage, datapoint2.tmp);
});
device.on("SMS", function(listeInfo) {
    sendSMS(listeInfo.voltage, listeInfo.tmp);
});

Device :

// Alias the GPIO pin as 'button'<br>button <- hardware.pin1;
led <- hardware.pin9;
led.configure(DIGITAL_OUT);
led2 <- hardware.pin8;
led2.configure(DIGITAL_OUT);
tmp36 <- hardware.pin7;
tmp36.configure(ANALOG_IN);
doorStatus <- hardware.pin2;
doorStatus.configure(DIGITAL_IN_PULLDOWN);
// global variable to track current state of LED pin
//etat <- 0;
// set LED pin to initial value (0 = off, 1 = on)
//led.write(etat);
function boucle() 
{
     local Vout = tmp36.read();
local tmp = ((3.3*Vout/65535)-0.5)*100  ;
    local voltage = hardware.voltage(); 
local datapoint2 = {
    "voltage" : voltage,
    "tmp" : tmp
}
     agent.send("mail",datapoint2);
local id = hardware.getdeviceid();
local datapoint = {
    "id" : id,
    "temp" : tmp
}
agent.send("data",datapoint);
   //    local rssi = imp.rssi();
     //agent.send("mail", rssi);
         local i; 
  for (i=0; i<10; i++)
          {
            led.write(0);         // set LED pin to new value
            imp.sleep(0.05);
            led.write(1);         // set LED pin to new value
            imp.sleep(0.05);
        // The button is released
        server.log("Release");
          }
         //imp.deepsleepfor(10);
          server.log("Press");
          imp.deepsleepfor(900);
}
function buttonPress() 
{
    
     // imp.onidle( agent.send("SMS","toto"))
// local Vin = hardware.voltage();
}
     local onlyOne = 0; 
function main() {
 
                local statedoorStatus = doorStatus.read();
                if (statedoorStatus == 0)
                    {
                    boucle();   
                    } else {
    
                            if (onlyOne ==0)
                                {
                                
                                local Vout = tmp36.read();
                                local tmp = ((3.3*Vout/65535)-0.5)*100  ;
                                local voltage = hardware.voltage(); 
                                local listeInfo = {
                                "voltage" : voltage,
                                "tmp" : tmp
                                }
                                
                                agent.send("SMS",listeInfo);
                                onlyOne = 1;
                                }
                            local i; 
                            for (i=0; i<10; i++)
                                {
                                led.write(0);         // set LED pin to new value
                                imp.sleep(0.1);
                                led.write(1);         // set LED pin to new value
                                imp.sleep(0.1);
                                }
                            }
                imp.wakeup(0.001, main);
}
button.configure(DIGITAL_IN_WAKEUP,buttonPress);
main();