Skip to content

How to create a thing

Ulf edited this page Aug 22, 2013 · 17 revisions

What will the thing do for us?

We will create a thing which sends mails if it gets a message from a specific driver from a specific node with a specific body. All other messages, which will come this node will be logged with a warning.

Before we can send the email, we have to initialize the driver, because we have to start an external application. This will be done in the init function.

Note: For sending the emails we will use gen_smtpc which is a simple mail client.

Ok, let's start

  1. Create a new module in the app/horst/src directory.
-module(mail_client_driver).

-export([init/1,handle_msg/3]).

init(Config) ->
	lager:info("mail_client_driver:init('~p')", [Config]),	
	application:start(gen_smtpc).

handle_msg([Node ,Sensor, Id, Time, "RISING"], Config, Module_config) ->
	{init, Flag, [{options,Options}]} = lists:keyfind(init, 1, Module_config),
	gen_smtpc:send({"sender", "password"}, "to", "Motion detected", "Motion detected", Options),
	lager:info("send mail notification"),
	Config;
handle_msg([Node ,Sensor, Id, Time, Body], Config, Module_config) ->
	lager:warning("mail_client_driver got the wrong message : ~p", [[Node ,Sensor, Id, Time, Body]]),
	Config.

#things.config

The things.config is the configuration file where you can enable/disable and configure your things.

{thing, "Mail_Client", 
	[
	{type, actor}, 
	{driver, {mail_client_driver, handle_msg}, [{init, true, [{options, [{use_ssl, true}, {host, "smtp.gmail.com"}, {port, 465}]}]}]},
	{activ, true},
	{timer, 0},
	{database, []},
	{description, "Mail Client for sending notification."}
	]}.

The new thing is named "Mail_Client". The name must be unique in your enviroment. The thing is from type actor. The driver tag describes the your thing. You can read like this: The driver is implemented in the module mail_client_driver and entry function is handle_msg. Note: it is implicit that you have 3 arguments. The arguments are: Message, Config, Module-Config.

Here, the module config contains the following elements :

  • init true means that we need a init function inside our driver and that it will be called during init phase.
  • options [list of parameters] These option are passed to gen_smtpc application when we send an email.

The timer is not used The database is not used The description contains only text which describes the thing.

Try it

Now we can go into the horst directory and compile everthing.

ua@ua-TA880GB:~/Dropbox/projects/erlang/sensor/horst$ make
==> goldrush (compile)
==> lager (compile)
==> gpio (compile)
==> erlib (compile)
==> sue (compile)
==> gen_smtpc (compile)
Compiled src/gen_smtpc_app.erl
Compiled src/gen_smtpc_sup.erl
Compiled src/gen_smtpc.erl
==> horst (compile)
==> horst (compile)

if you don't get any error you can start horst by typing:

ua@ua-TA880GB:~/Dropbox/projects/erlang/sensor/horst$./dev.sh

In the log output you will see that the init function of the mail_client_driver is called and that the gen_smtpc application is started.

mail_client_driver:init('[{options,[{use_ssl,true},{host,"smtp.gmail.com"},{port,465}]}]')
08:58:40.517 [info] Application horst started on node 'horst@ua-TA880GB' gen_smtpc_sup started ... 

If you want to disable the mail_client thing you don't have to stop horst. you only edit the things.config and set activ to false. Horst will do the rest for you, as you can see in the log.

09:01:50.699 [info] Config file : "things.config" must be updated!
09:01:50.703 [info] update the list of sensors and actors, because the things.config changed
09:01:50.704 [info] terminated thing with result : "Mail_Client"

Note:

If you also had installed Moni on your machine you can have a look at your new thing. ... more later

Complete the implementation

Now well implement the sending of an email with the mail_client thing.

handle_msg([Node ,Sensor, Id, Time, "RISING"], Config, Module_config) ->
	Options = proplists:get_value(options, Module_config, []), 
	gen_smtpc:send({"sender ", "password"}, "to", "Test", "Test Body", Options),
	Config.

From the module config we take the options list, because we need this for sending the email. We return the whole config in the last line, because the config is stored in the thing. ... more later

That's all about the implementation. You only have to replace sender, passwort and to with real values.

Messages.config

Now your thing is ready to work, but wait a second. WHo or what will trigger the mail_client to send a mail? In this example, the mail_client will send a message if the motion sender detects a motion. The motion sender is deployed on another raspberry pi. It sends messages in form of :

[<<"horst@raspberrypi">>,<<"hc_sr501_driver">>,<<"0">>,<<"63544382862">>,"RISING"]

  • horst@raspberrypi the node from which the message comes from
  • hc_sr501_driver the driver / module which created the message
  • 0 is the id of the driver / module.
  • 63544382862 the time when the message was created
  • "RISING" the body of the message. Here it means, that the motion sender detected a motion.

Now we edit our messages.config file to say that our mail_client will react on this message.

{mail_client_driver, [{<<"horst@raspberrypi">>,<<"hc_sr501_driver">>,<<"0">>}]}.

If horst was stopped and you start horst again, the mail_client will act on the messages from the motion sender. If horst is already running, the messages.config will be reloaded and that's all.