23 feb 2014
i love ambient illumination so i installed about 10 different LED systems into my room. the downside is that controlling that many devices manually, which also includes two TFT monitors and my stereo. this post documents the various software designs i tried until i ended up with a node.js installation on a raspberry pi (PI for short) which is no used several times a day to control my devices’ power states.
WARNING - DISCLAIMER:
i’m no expert in electrical engineering - so if you copy this work, ask an expert to check on your setup before making daily use. especially check these things: ***
in fact, i’ve chosen tinkerforge dual relais bricklets over a self-built relais to avoid making critical errors which could result in your house burned to the ground or lives put to danger.
I’M NOT RESPONSIBLE IF YOUR DEVICE KILLS YOUR CAT OR BURNS DOWN YOUR HOUSE - YOU HAVE TO KNOW WHAT YOU ARE DOING!
prior to this self-made solution i was considering remote controlled electrical switches.
the problems i had with these were a mixture of:
reliability problems
i need to know if a trigger command really worked, if not i could have used the remote switch bricklet [14]
short lifespan
remote controlled electrical switches start to break after 1-2 years; a sign is that you have to trigger the ON-key several times or that you can’t force them OFF anymore…
too expensive
openHAB http://www.openhab.org/features-tech.html seems to be interesting but i think it is quite complex i wouldn’t know if that stuff works the way i want it to
horrible usability
no app support, if so these apps often rely on proprietary infrastructure
example: http://www.eq-3.de/produkt-detail-zentralen-und-gateways/items/homematic-zentrale-ccu-2.html
probably most vendors do not provide a REST interface
security issues because of:
because of this built my own device for controlling 6x 230V using my PC, phone, tablet or a 3x4 key pad. as a nice side-effect this also gave me the opportunity to play with different programming languages/web development tools.
here is my setup:
the setup consists of:
raspberry pi (model b)
tinkerforge
the following 3 images show my prototype which, at that time, did not include the multi touch bricklet but instead a 4th dual relais.
my first setup using tinkerforge [1] hardware and controlled it from my laptop using USB:
|- masterbrick
|A- dual relias bricklet (2 230V relais)
|B- dual relias bricklet (2 230V relais)
|C- dual relias bricklet (2 230V relais)
the first impression of tinkerforge’s hardware and software were promising. i integrated the tinkerforge components into a breaker box but i didn’t add any fuses. tinkerforge relies on a computer taking control of the stack every time you want the state to change and if you unplug the usb cable all relais are set to their initial position, which is OFF.
since i wanted to control the stack from my mobile phone and tablet (as well as from my laptop) i bought the, back then, brand new WIFI extension [2]. i would have bought the ethernet extension [3] if it had existed back then. the configuration was pretty easy, but that connection wasn’t too great because of the bad WIFI signal and maybe some problems between the wifi extension and the d-link router. anyway i was able to control the stack most of the time without having to reset my tinkerforge stack by power cycling the stack.
|- masterbrick
| |- WIFI Extension
|A- dual relias bricklet (2 230V relais)
|B- dual relias bricklet (2 230V relais)
|C- dual relias bricklet (2 230V relais)
i was using the WIFI extension for weeks but it turned out that my reception wasn’t very good and had a lot connection issues (probably caused by bad SNR with additional D-Link quirks).
so i came up with a new solution: i added a raspberry pi to the stack:
|- raspberry pi
|- masterbrick
|A- dual relias bricklet (2 230V relais)
|B- dual relias bricklet (2 230V relais)
|C- dual relias bricklet (2 230V relais)
|D- multi touch bricklet
|- 3x4 key pad
at tinkerforge they are currently designing the ‘red brick’ http://www.tinkerforge.com/en/blog/2014/2/21/tinkerforge-goes-stand-alone-aka-red-brick. i’m really looking forward to having one!
tinkerforge ‘master brick’ and ‘WLAN extension’ weren’t measureable so the 1,8W are caused soly by the raspberry pi ;-)
requirements:
usability optimized for touch screens (big buttons/adaptive layout)
interface which can be controlled via curl (or similar) - REST
every attached browser instance must reflect the state (without having to do manual page reloads), see [6]/[7]
must be running reasonable fast:
i experimented with different languages:
my initial design was to use the master brick with the WIFI master extension. i designed a native android application (java) using the android SDK [8]. it took me one day to write a basic client application for the nexus 7 and i would like to point out that the android SDK has a remarkable documentation and workflow.
native android application drawbacks:
client/server implementation (HTTP) advantages:
some remarks about the installation:
after the first boot, i had a keyboard/screen attached and configured these values:
i had been playing with ruby on rails so far but, after i’ve been talking to stefan schlott [3] about my project, i changed my mind and continued using [4] scala/lift.
Lift code is as clean and brief as Rails, yet performs at least 6 times faster and is multithreaded. Additionally, because Scala is strongly typed, the compiler catches type errors.
lift implements ajax and comet [9]/[10] and [11] to make the DOM-tree dynamically changable (without having to implement page reloads) - i love this!
i was using IntelliJ [12] for doing most scala/lift development, this is really a great IDE!
in regards to deployment i found it encouraging that there are several ppl using jetty on the raspberry pi already and that there is a collection of high quality examples about what can be done with lift, see [5] and [6].
additional software:
apt-get install vim htop screen jetty8 openjdk-7-jdk
after that i create a war package:
./sbt
package-war
various jetty optimizations:
JAVA_OPTIONS="-Xmx256m -Drun.mode=production -noverify" # 3 seconds
#JAVA_OPTIONS="-Xmx256m -Djava.awt.headless=true -noverify -Drun.mode=production" # 3 seconds
# Home of Java installation.
JAVA_HOME="/usr/lib/jvm/java-7-openjdk-armhf/"
after i applied the optimization i tested the chat app again:
the comet roundtrip time was from hitting return on the client and seeing the view updates on the client is about 2250 ms.
the comet roundtrip time was from hitting return on the client and seeing the view updates on the client is about 273 ms.
in both cases this means 100% PI CPU usage for the shown time.
restarting jetty took about 1-3 minutes after heavy optimizations, which i can’t remember right now. clicking button using comet took about 1 second of 100% cpu load on the PI until the other clients were updated. however, i was using openjdk which is AFAIK not optimized for ARM and also lacks JIT (runtime optimization). about 2-4 months after i started using scala oracle released embedded java (or similar) but i didn’t try it
i don’t like the fact that i need to edit/build the application on a different system than the PI since the java IDEs like IntelliJ or eclipse are very demanding
i didn’t find out how to make the comet (or java) faster and wonder why [13] seems to be so fast
scala with lift seems to be a very cool framework and probably got potential
lift comets are implemented using ‘long polling’ [13] and are not based on websockets yet:
the manual says:
Lift’s current Comet implementation uses long polling. In the future, Lift will also use WebSockets, but the WebSocket API and implementation isn’t “baked” yet, and Lift’s current implementation works well for browsers from IE6 on. Lift’s long polling implementation opens a single HTTP connection from the browser to the server if one or more Comet components are detected on a HTML page. The request contains a list of the components and the “version” for each of the components. If the version number of any of the components on the server is “newer” than the version on the client, the deltas are sent as the response, the connect is closed, the browser applies the deltas and then re-opens the HTTP connection (with HTTP 1.1 keep-alive this does not imply reopening a TCP/IP connection.) If the version of the component changes while the HTTP “poll” is open, the deltas are sent down as a response and the connection is closed. If no state changes after 110 seconds (this is a tunable parameter), a noop is sent to the browser and the browser re-opens the HTTP connection. The 110 second timeout is to insure that Lift’s comet implementation is proxy friendly.
i like socket.io for node.js which implements websockets where possible and uses long polling as fallback already.
compiling node on the PI took about 30-70 minutes IIRC. the first ‘hello world’ applications were easy to understand and were very fast.
the source for this project can be found here:
https://github.com/qknight/relais.js/blob/master/relais.js/
my first problem was that i didn’t understand MVC in node.js. i was trying ember.js to get realtime sync in the views without realizing that most of these frameworks are, despite what MVC might imply, not doing that. most of them require a F5 refresh to sync the views but i wanted sync in realtime. since i was new to node programming i didn’t understand how to keep track of all websocket contexts at first but after reading the excellent code from Olli K [5] it dawned on me.
at the time of this writing i was still using websockets directly, like done in example [5], instead of using socket.io. but i’d like to adapt to socket.io.
see: http://vuejs.org/perf/ Performance Comparisons
since there are no node.js bindings for the tinkerforge
library (update 24.2.2014 14:14: see http://www.tinkerunity.org/forum/index.php/topic,2216.0.html).
anyway, i’m still using using c-programs to access the tinkerforge
stack:
relais-tool - https://github.com/qknight/relais.js/tree/master/relais-tool
is queried and returns a JSON formaitted answer which is processed
keypad-tool - https://github.com/qknight/relais.js/tree/master/keypad-tool
reports 3x4 key pad changes via JSON formatted to server.js
the integration is actually pretty simple and it is using stdin parsing with JSON messaging!
since i want to use curl based scripts to access the relais, here is a bash shell script for triggering relais:
cat .trigger_relais
#!/bin/sh
relais=$1
cred="admin:admin"
ip="192.168.0.48"
state=$(curl --user "$cred" http://${ip}/state/${1})
nstate="0"
if [ "$state" == "0" ]; then
nstate=1
else
nstate=0
fi
echo $nstate
curl --user "$cred" -i -X PUT -H 'Content-Type: application/json' -d '{"value": "'$nstate'"}' http://${ip}/state/$1
with this command line:
./.trigger_relais 1
to start the node application after each boot i do:
edit your crontab using ‘crontab -e’:
@reboot /root/relais.js/starter.sh
note: if the process crashes (or it receives a exception) it won’t be restarted automatically. if that gets a problem i’ll add a while true; do …; done loop into starter.sh
usability: using my device is so cool as all interfaces are very responsive and work reliably, better than anything i had been using before.
tinkerforge development is impressive. back when i started using it there was no WIFI extension, no multi touch bricklet and when writing this article i saw the exciting ‘red brick’ blog announcement - which could get a nice raspberry pi replacment if it runs using linux of course! i’m now using this hardware every day, for at least on year now, and so far it is rock solid.
node.js is a powerful framework and is very fast on the PI. i can’t stress this fact enough - really, try it!
things which would be cool to have:
if you want to give me feedback, please mail to: js@lastlog.de
see also: https://news.ycombinator.com/item?id=7384549
images were taken (and remixed by me) from: