I really
like the concept of BeagleBone and Cloud9 IDE. I have my board connected directly to my
local intranet with Ethernet cable, so I can access the IDE and my saved project, and continue working at any
PC in my household, no matter whether it’s the ChromeBook, my company Windows
Ultrabook, or my wife's MacBook. The very same user experience available with
zero-installation needed. And my project is secured, as it is stored locally at
the mass memory of the board itself. No one can access it from outside of my
intranet. Of course, in case of professional software development, version control, collaboration,
backups, etc. needs to be considered separately.
The default
Ångström Linux image installed on BeagleBone, does not have the WebSocket
Javascript library socket.io installed by default. At GitHub BoneScript Socket.IO page
there are instructions how to install socket.io. The whole project was initially committed only two
weeks ago. There is also a nice, but rather complex example of using WebSocket
to remote control LEDs, which needs to be externally attached to the BeagleBone
board. NB! Some hardware hacking required.
I wrote a
canonical code example demonstrating how to control an onboard LED at BeagleBone.
So, no hardware hacking is needed to test the code. JavaScript uses JSON (JavaScript Object
Notation) to exchange data. In this example, very simple JSON messages are
delivered over the WebSocket connection to control and confirm the LED state.
BoneScript functions are used for hardware access.
JSON
messages in this example have the following simple syntax:
{"name":"led","args":["on"]}
The demo
consists of two files located in sockserv folder. Socketserver.js, which is the Node.JS executed at
BeagleBone, and socketclient.html which is the web page delivered to web browser upon request,
containing HTML and JavaScript code for communication with the Beagle. The
architecture equals to the scenario #1, presented in my previous posting.
Let’s
take a closer look at few key functions.
Server side
This is how
the "web server" is implemented. Whenever a client is connected and sends any GET
command, the static socketclient.html file is read from local the flash disk at beagle,
and send to the browser.
function
httpserver (req, res) {
fs.readFile('sockserv/socketclient.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading
index.html');
}
res.writeHead(200);
res.end(data);
});
}
When
WebSocket connection is established, and some data received, the following
callback will parse the message, whether the LED should be switched ON or OFF. As an
acknowledgement, the same message is transmitted back to the client.
io.sockets.on('connection',
function (socket) {
socket.on('led', function (data) {
console.log(data);
if (data == 'on'){
b.digitalWrite(led, b.HIGH);
socket.emit('led', 'on');
}else{
b.digitalWrite(led, b.LOW);
socket.emit('led', 'off');
}
});
});
Client side
At the socketclient.html page, there is one button to toggle the state of the LED. When the
button is clicked, this function transmits JSON message over WebSocket to
server.
function toggleLed(){
if (
document.getElementById("ledButton").value == "Switch On" )
{
socket.emit('led', 'on');
} else {
socket.emit('led', 'off');
}
}
If
acknowledgement is received, it it processed by this callback function, which
changes the state of the button, confirming successful operation to user. If you see the label of the button changed, you know the message has travelled back and forth.
socket.on('led', function (data) {
console.log(data);
if (data == 'on'){
document.getElementById("ledButton").value= "Switch
Off";
} else {
document.getElementById("ledButton").value= "Switch
On";
}
});
There is
one flaw in beauty in this code. Once the page is loaded, the button is not
initially synchronized with the actual state of the physical LED. Only after
clicking the button for the first time, the UI and the LED are in sync. I
made this decision by purpose, as I want to keep the example as simple as
possible.
|
Web UI of the demo. |
Disclaimer: I’m not a professional JavaScript programmer,
actual this was my first Node.JS code written ever, and only few times tried
JavaScript before. Thus, the code may not be optimal, and something I may have
understood wrong. I warmly welcome any feedback to correct faults, and to make
it pedagogically more correct. Well, it just looks like working OK.