Difference between revisions of "Erlang"

From eLinux.org
Jump to: navigation, search
m
m
(13 intermediate revisions by the same user not shown)
Line 1: Line 1:
Erlang on RPi, starting with a fresh 2013-05-25-wheezy-raspbian.zip image.
+
Erlang on RPi, starting with a fresh wheezy-raspbian image. Erlang takes a couple of hours to compile (when you run "make").
  
 
<code><pre>
 
<code><pre>
Line 5: Line 5:
 
sudo apt-get install libssl-dev
 
sudo apt-get install libssl-dev
 
sudo apt-get install ncurses-dev
 
sudo apt-get install ncurses-dev
wget http://www.erlang.org/download/otp_src_R16B01.tar.gz
+
wget http://www.erlang.org/download/otp_src_R16B02.tar.gz
tar -xzvf otp_src_R16B01.tar.gz
+
tar -xzvf otp_src_R16B02.tar.gz
cd otp_src_R16B01/
+
cd otp_src_R16B02/
 
./configure
 
./configure
 
make
 
make
Line 15: Line 15:
 
== Introduction ==
 
== Introduction ==
  
Erlang is a programming language which has many features more commonly associated with an operating system than with a programming language: concurrent processes, scheduling, memory management, distribution, networking, etc. On this page I will show how to use Erlang on RPi to put a sensor value from Gertboard on the web using an interface written in [[Forth]] and how to put a picture from Pi Camera on the web.
+
On this page I will show how to use Erlang on RPi to put a sensor value from Gertboard on the web using an interface written in [[Forth]] and how to put a picture from Pi Camera on the web.
 
+
== Concurrency ==
+
Erlang has extremely lightweight processes whose memory requirements can vary dynamically. Processes have no shared memory and communicate by asynchronous message passing. Erlang supports applications with very large numbers of concurrent processes. No requirements for concurrency are placed on the host operating system.
+
 
+
== Distribution ==
+
Erlang is designed to be run in a distributed environment. An Erlang virtual machine is called an Erlang node. A distributed Erlang system is a network of Erlang nodes (typically one per processor). An Erlang node can create parallel processes running on other nodes, which perhaps use other operating systems. Processes residing on different nodes communicate in exactly the same was as processes residing on the same node.
+
 
+
== Robustness ==
+
Erlang has various error detection primitives which can be used to structure fault-tolerant systems. For example, processes can monitor the status and activities of other processes, even if these processes are executing on other nodes. Processes in a distributed system can be configured to fail-over to other nodes in case of failures and automatically migrate back to recovered nodes.
+
 
+
== Soft real-time ==
+
Erlang supports programming "soft" real-time systems, which require response times in the order of milliseconds. Long garbage collection delays in such systems are unacceptable, so Erlang uses incremental garbage collection techniques.
+
 
+
== Hot code loading ==
+
Many systems cannot be stopped for software maintenance. Erlang allows program code to be changed in a running system. Old code can be phased out and replaced by new code. During the transition, both old code and new code can coexist. It is thus possible to install bug fixes and upgrades in a running system without disturbing its operation.
+
 
+
== Incremental code loading ==
+
Users can control in detail how code is loaded. In embedded systems, all code is usually loaded at boot time. In development systems, code is loaded when it is needed, even when the system is running. If testing uncovers bugs, only the buggy code need be replaced.
+
  
 
== A Web Server ==
 
== A Web Server ==
Erlang is a perfect language to use for programming a web server, and that is exactly what Loïc Hoguin did. Cowboy is one of the most scalable web servers there is and it's also small so it fits nicely in a RPi. I was thinking of using it to display the kW load from my [[Forth | Atlast Forth]] interface to  [[RPi Gertboard | Gertboard]]. Here is how I did it, first install the cowboy web server and test run it:
+
Erlang is a perfect language to use for programming a web server, and that is exactly what Loïc Hoguin did. [http://www.ninenines.eu] Cowboy is one of the most scalable web servers there is and it's also small so it fits nicely in a RPi. I was thinking of using it to display the kW load from my [[Forth | Atlast Forth]] interface to  [[RPi Gertboard | Gertboard]]. Here is how I did it, first install the cowboy web server and test run it:
 
<code><pre>
 
<code><pre>
 
sudo apt-get install git
 
sudo apt-get install git
Line 45: Line 27:
 
To make it run you first have to tell it to accept HTTP:
 
To make it run you first have to tell it to accept HTTP:
 
<code><pre>
 
<code><pre>
cd ebin
+
cd ~/cowboy/ebin
 
cp examples/hello_world/src/hello_world.app.src ./hello_world.app
 
cp examples/hello_world/src/hello_world.app.src ./hello_world.app
 
erlc ../examples/hello_world/src/*.erl
 
erlc ../examples/hello_world/src/*.erl
 
cd ..
 
cd ..
 
cp examples/hello_world/start.sh .
 
cp examples/hello_world/start.sh .
sudo ./start.sh
+
./start.sh
 
</pre></code>
 
</pre></code>
 
Start a browser and point it to your RPi:8080, eg 192.168.0.178:8080
 
Start a browser and point it to your RPi:8080, eg 192.168.0.178:8080
Line 85: Line 67:
 
cd to ebin and compile the file:
 
cd to ebin and compile the file:
 
<code><pre>
 
<code><pre>
cd ebin
+
cd ~/cowboy/ebin
 
erlc ../examples/hello_world/src/toppage_handler.erl
 
erlc ../examples/hello_world/src/toppage_handler.erl
 
</pre></code>
 
</pre></code>
Line 94: Line 76:
 
In directory cowboy, create a directory priv and copy atlast to it:
 
In directory cowboy, create a directory priv and copy atlast to it:
 
<code><pre>
 
<code><pre>
 +
cd ~/cowboy
 
mkdir priv
 
mkdir priv
 
cp ../atlast-1.2/atlast ./priv
 
cp ../atlast-1.2/atlast ./priv
Line 106: Line 89:
 
: w 25 getkwh 2drop 25 getkwh 36 * swap 100 / / ." "w=" . cr ;
 
: w 25 getkwh 2drop 25 getkwh 36 * swap 100 / / ." "w=" . cr ;
 
</pre></code>
 
</pre></code>
Ok, now we just have to call start.sh again and point the browser to 192.168.0.178:8080 or whatever ip address you have on your RPi. After a few seconds the W load should show up. I stop here, this is not the right forum to discuss how to make a web gui, lots of other sites can help with that. Have fun :)
+
Ok, now we just have to call start.sh again ( sudo is needed by the Gertboard driver, not by Cowboy, and for pure simplicity I take another shortcut and starts the Cowboy with sudo rights. Don't do this in a production environment).
 +
<code><pre>
 +
sudo ./start.sh
 +
</pre></code>
 +
Point the browser to 192.168.0.178:8080 or whatever ip address you have on your RPi. After a few seconds the W load should show up. I stop here, this is not the right forum to discuss how to make a web gui, lots of other sites can help with that. Have fun :)
  
 
Note: The suggested way to call the port directly from examples/hello_world/src/toppage_handler.erl is just to make it easy. In a real website with thousands of users you should open the port from a separate process and let it run and serve more than one web call.
 
Note: The suggested way to call the port directly from examples/hello_world/src/toppage_handler.erl is just to make it easy. In a real website with thousands of users you should open the port from a separate process and let it run and serve more than one web call.
  
 
== External Interfaces - Pi Camera ==
 
== External Interfaces - Pi Camera ==
If you have a PiCamera and wants to have a picture on a web page, check that /opt/vc/bin/raspistill works on your system, then replace the code in examples/hello_world/src/toppage_handler.erl with the following: (Follow the Gertboard example for compiling and running). The cool thing with this is that it's in real time, it is not a file that is served but a new picture is taken when you do the web call.
+
If you have a PiCamera and wants to have a picture on a web page. The cool thing with this is that it's in real time, it is not a file that is served but a new picture is taken when you do the web call. Check that /opt/vc/bin/raspistill works on your system, then replace the code in examples/hello_world/src/toppage_handler.erl with the following: (Then follow the Gertboard example for compiling and running).  
 
<code><pre>
 
<code><pre>
 
%% @doc Hello world handler.
 
%% @doc Hello world handler.

Revision as of 21:24, 18 September 2013

Erlang on RPi, starting with a fresh wheezy-raspbian image. Erlang takes a couple of hours to compile (when you run "make").

sudo apt-get install wget
sudo apt-get install libssl-dev
sudo apt-get install ncurses-dev
wget http://www.erlang.org/download/otp_src_R16B02.tar.gz
tar -xzvf otp_src_R16B02.tar.gz
cd otp_src_R16B02/
./configure
make
sudo make install

You start the interactive shell with erl and quit with Ctrl-g q. Read about Erlang here [1]

Introduction

On this page I will show how to use Erlang on RPi to put a sensor value from Gertboard on the web using an interface written in Forth and how to put a picture from Pi Camera on the web.

A Web Server

Erlang is a perfect language to use for programming a web server, and that is exactly what Loïc Hoguin did. [2] Cowboy is one of the most scalable web servers there is and it's also small so it fits nicely in a RPi. I was thinking of using it to display the kW load from my Atlast Forth interface to Gertboard. Here is how I did it, first install the cowboy web server and test run it:

sudo apt-get install git
git clone git://github.com/extend/cowboy.git
cd cowboy
make

To make it run you first have to tell it to accept HTTP:

cd ~/cowboy/ebin
cp examples/hello_world/src/hello_world.app.src ./hello_world.app
erlc ../examples/hello_world/src/*.erl
cd ..
cp examples/hello_world/start.sh .
./start.sh

Start a browser and point it to your RPi:8080, eg 192.168.0.178:8080

External interfaces - Gertboard

Erlang processes communicate with the outside world using the same message passing mechanism as used between Erlang processes. This mechanism is used for communication with the host operating system and for interaction with programs written in other languages. If required for reasons of efficiency, a special version of this concept allows e.g. C programs to be directly linked into the Erlang runtime system. The easy way is good enough so just open a port to Atlast Forth in the file examples/hello_world/src/toppage_handler.erl. Replace toppage_handler.erl with the following:

%% @doc Hello world handler.
-module(toppage_handler).

-export([init/3]).
-export([handle/2]).
-export([terminate/3]).

init(_Transport, Req, []) ->
        {ok, Req, undefined}.

handle(Req, State) ->
  Port = open_port({spawn, "./priv/atlast -i./priv/kwh.atl"}, [{line,40}]),
  Port ! {self(), {command, "1 gertboard\n"}},
  Port ! {self(), {command, "w\n"}},
  receive
    {Port,{data,{eol,D}}} -> D
  after 20*1000 -> D = "timeout"
  end,
  Port ! {self(), {command, "0 gertboard\n"}},
  port_close(Port),
  {ok, Req2} = cowboy_req:reply(200, [], D, Req),
  {ok, Req2, State}.

terminate(_Reason, _Req, _State) ->
        ok.

cd to ebin and compile the file:

cd ~/cowboy/ebin
erlc ../examples/hello_world/src/toppage_handler.erl

Now, we need to put atlast in the ./priv directory, but first we have to get rid of the banner and the prompt.

In atlmain.c comment out PR("ATLAST 1.2 (2007-10-07) This program is in the public domain.\n"); at line 55 and comment out if (!fname) at 162,163,164 and 165. Save and run make again.

In directory cowboy, create a directory priv and copy atlast to it:

cd ~/cowboy
mkdir priv
cp ../atlast-1.2/atlast ./priv

Create a file kwh.atl and put it in the same priv directory with the word definitions for getting kW and W load values from Gertboard:

( The first 25 getkwh is for detecting an edge, drop the result and find next edge. Convert the two integers to float and divide them.  )
( 3.6 divided by the result. The result is load in kilowatts )
: kw 3.6 25 getkwh 2drop 25 getkwh float 2 roll float 2swap f/ f/ ." "kw=" f. cr ;

( The same thing done with integers only, here the result is in W )
: w 25 getkwh 2drop 25 getkwh 36 * swap 100 / / ." "w=" . cr ;

Ok, now we just have to call start.sh again ( sudo is needed by the Gertboard driver, not by Cowboy, and for pure simplicity I take another shortcut and starts the Cowboy with sudo rights. Don't do this in a production environment).

sudo ./start.sh

Point the browser to 192.168.0.178:8080 or whatever ip address you have on your RPi. After a few seconds the W load should show up. I stop here, this is not the right forum to discuss how to make a web gui, lots of other sites can help with that. Have fun :)

Note: The suggested way to call the port directly from examples/hello_world/src/toppage_handler.erl is just to make it easy. In a real website with thousands of users you should open the port from a separate process and let it run and serve more than one web call.

External Interfaces - Pi Camera

If you have a PiCamera and wants to have a picture on a web page. The cool thing with this is that it's in real time, it is not a file that is served but a new picture is taken when you do the web call. Check that /opt/vc/bin/raspistill works on your system, then replace the code in examples/hello_world/src/toppage_handler.erl with the following: (Then follow the Gertboard example for compiling and running).

%% @doc Hello world handler.
-module(toppage_handler).

-export([init/3]).
-export([handle/2]).
-export([terminate/3]).

init(_Transport, Req, []) ->
        {ok, Req, undefined}.

handle(Req, State) ->
  Port = open_port({spawn, "/opt/vc/bin/raspistill -t 2 -w 1024 -h 768 -o -"}, [binary]),
  Str = loop(Port,<<>>), 
  {ok, Req2} = cowboy_req:reply(200, [], Str, Req),
  {ok, Req2, State}.

terminate(_Reason, _Req, _State) ->
        ok.

loop(Port,Frame) ->
  receive			
    {Port, {data, Chunk}} -> 
      Size = byte_size(Chunk) - 2,
      case Chunk of 
        <<_:Size/binary,255,217>> -> Framestring = base64:encode_to_string(<<Frame/binary,Chunk/binary>>),
                  "<html><img src = 'data:image/jpeg;base64," ++ Framestring ++ "'></html>";
    _ -> loop(Port,<<Frame/binary,Chunk/binary>>)
  end
  after 20*1000 -> "<html>timeout</html>"
  end.

Note: The suggested way to call the port directly from examples/hello_world/src/toppage_handler.erl is just to make it easy. In a real website with thousands of users you should open the port from a separate process and let it run and serve more than one web call.