Tuesday, April 24, 2018

Driving and monitoring your machines with emails, from Java

Here is the problem

You have your network at home, with several machines connected to it (laptops, tablets, Raspberry PIs, phones, etc). Your home network is a Local Area Network (aka LAN), the machines can see each other, but they cannot be seen from outside, from the Internet.
You may very well want to deal with those machines while away from home, to restart services, launch a new program, or even reboot.
In the configuration mentioned above, this is simple, you just cannot do it. And that is frustrating!
There is a way though. Those machines on your home LAN can send and receive emails...

Using JavaMail

JavaMail is a Java package that has been available for ever, it understands the email protocols (IMAP, POP3, SMTP, etc), and can be used to interact with email accounts programmatically.

An example

There is an example of such an interaction on this github repository.
The fastest way to get it running is to run the following commands (these are for Linux - and MacOS - on Windows, use the git shell):
$ git clone https://github.com/OlivierLD/raspberry-pi4j-samples.git
$ cd raspberry-pi4j-samples
$ cd common-utils
$ ../gradlew shadowJar
$ cp email.properties.sample email.properties
$ vi email.properties
$ # Here you modify your properties file to match your email account
$ java -cp ./build/libs/common-utils-1.0-all.jar email.examples.EmailWatcher -send:google -receive:google
The -send:google -receive:google depends on the settings in your email.properties.
Then, to the account mentioned in the email.properties, send a message like this:
Subject: execute
Content:
whoami
ifconfig
uname -a
Note: this example requires the content to be in plain/text.
Once the message is received by the EmailWatcher, it sends you an acknowledgement:
Then, the 3 commands are processed by the EmailWatcher, you would see in its console an output like that:
Start receiving.
Received:
whoami
ifconfig
uname -a

Operation: [execute], sent for processing...
pi
lo0: flags=8049 mtu 16384
 options=1203
 inet 127.0.0.1 netmask 0xff000000 
 inet6 ::1 prefixlen 128 
...
And finally, you receive an email like that:
... meaning that the commands you've sent have been executed.

Comments

This process is not synchronous, this could ba drawback... But still, it allows you to interact remotely with machines unvisible from the Internet.

Having the command

java -cp ./build/libs/common-utils-1.0-all.jar email.examples.EmailWatcher -send:google -receive:google
fired when the machine boots will allow you make sure it is waiting for your emails as soon as the machine is up.

This EmailWatcher as it is also allows you to execute scripts, attached to the email. Look into the code for details ;)
It is even possible to ssh to another machine and execute a bunch of commands stored in a script... The command you send in the email's body would be like

ssh pi@192.148.42.13 bash -s < ~/nodepi.banner.sh
You can even sudo, if a password is required, use sshpass:
sshpass -p 'secret-password' ssh pi@192.148.42.13 bash -s < ~/nodepi.sudo.sh
This can be dangerous, hey? With great power come great responsibilities...

Sunday, April 15, 2018

HeadsUp DIsplay

The idea here is to display a screen on a transparent support - like a wind shield.
The data are displayed on the screen, reflected on the transparent support, and nothing is preventing you from seeing through it.
(Click the image to enlarge it)

Here is above an HTML page, tweaked by some CSS classes to mirror the data (as the page is reflected on the screen, the page content has to be displayed as in a mirror, and flipped upside down.). In this case, the page is rendered on Chromium in kiosk mode, running on a Raspberry PI with a touch screen attached to it.
CSS Classes:
    .mirror {
      display: block;
      -webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
      -moz-transform: matrix(-1, 0, 0, 1, 0, 0);
      -o-transform: matrix(-1, 0, 0, 1, 0, 0);
      transform: matrix(-1, 0, 0, 1, 0, 0);
    }

    .upside-down {
      height: 100%;
      width: 100%;
      -moz-transform: rotate(180deg);
      -webkit-transform: rotate(180deg);
      -ms-transform: rotate(180deg);
      -o-transform: rotate(180deg);
      transform: rotate(180deg);
    }

    .mirror-upside-down {
      display: block;
      -webkit-transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg);
      -moz-transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg);
      -o-transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg);
      transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg);
    }

In the picture above, we use the class as follow:
<div id="the-div" class="mirror-upside-down big" style="padding: 0px; text-align: center;">
  <hr/>
  <table>
    <tr>
      <td colspan="2">GPS Data</td>
    </tr>
    <tr>
      <td>
        <span>Your position:</span>
        <br/>
        <span>N 37° 44.93'</span>
...
The page on the screen (not on the wind shield) would actually look like this:

GPS Data
Your position:
N 37° 44.93'
W 122°30.42'
Your Speed:
12.34 kts

You can also work around the perspective effect on the reflected page by tweaking the CSS classes:
    .mirror-upside-down {
      display: block;
      -webkit-transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg) perspective(50em) rotateX(-40deg);
      -moz-transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg) perspective(50em) rotateX(-40deg);
      -o-transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg) perspective(50em) rotateX(-40deg);
      transform: matrix(-1, 0, 0, 1, 0, 0) rotate(180deg) perspective(50em) rotateX(-40deg);
    }

GPS Data
Your position:
N 37° 44.93'
W 122°30.42'
Your Speed:
12.34 kts
We call this the Star Wars effect. ;)

Possibilities are endless!
The full page is here.

Wednesday, April 11, 2018

Docker on the Raspberry PI

This post intends to illustrate how Docker can work around the "But it works on my machine!.." syndrome.

Let's say you have a nodejs project you want to share with others.
The application reads GPS data through a Serial port, and feeds a WebSocket server.
The data can then be visualized through a Web interface.

To enable everything, you need to:
  1. Have a Raspberry PI
  2. Flash its SD card and connect it to a network
  3. Install build tools
  4. Install git
  5. Install NodeJS and npm
  6. Clone the right git repository
  7. Install all the required node modules
  8. Drill down into the right directory
  9. Start the node server with the right script
  10. Access the Raspberry PI from another machine on the same network, and reach the right HTML page.

This is certainly not difficult, but there are many ways to do several mistakes at each step of the process!

Docker can take care of the steps 3 to 9. It will build the image, and then run it.
The image can also be pushed to a repository, so users would not have to build it.
Just to run it after downloading it.

The only pre-requisite would be to have installed Docker on the machine (the Raspberry PI here), as explained here.
Create a Dockerfile like this (available here):
 FROM resin/raspberrypi3-debian:latest

 LABEL maintainer="Olivier LeDiouris <olivier@lediouris.net>"

 RUN echo "alias ll='ls -lisah'" >> $HOME/.bashrc

 RUN apt-get update
 RUN apt-get install sysvbanner
 RUN apt-get install -y curl git build-essential
 RUN curl -sL https://deb.nodesource.com/setup_9.x | bash -
 RUN apt-get install -y nodejs
 RUN echo "banner Node-PI" >> $HOME/.bashrc
 RUN echo "git --version" >> $HOME/.bashrc
 RUN echo "echo -n 'node:' && node -v" >> $HOME/.bashrc
 RUN echo "echo -n 'npm:' && npm -v" >> $HOME/.bashrc

 RUN mkdir /workdir
 WORKDIR /workdir
 RUN git clone https://github.com/OlivierLD/node.pi.git
 WORKDIR /workdir/node.pi
 RUN npm install

 EXPOSE 9876
 CMD ["npm", "start"]

In this case, the full Docker image creation (named oliv-nodepi below) comes down to 1 line (the one in bold red):
 $ docker build -t oliv-nodepi .
Sending build context to Docker daemon  752.6kB
Step 1/20 : FROM resin/raspberrypi3-debian:latest
 ---> c542b8f7a388
Step 2/20 : MAINTAINER Olivier LeDiouris 
 ---> Using cache
 ---> b2ff0d7c489f
Step 3/20 : ADD nodepi.banner.sh /
 ---> 535733298dd1
Step 4/20 : RUN echo "alias ll='ls -lisah'" >> $HOME/.bashrc
 ---> Running in 09baf7261a55
Removing intermediate container 09baf7261a55
 ---> 71e1e4c95663
Step 5/20 : RUN apt-get update
 ---> Running in 5d817a941a14
Get:1 http://security.debian.org jessie/updates InRelease [94.4 kB]
Get:2 http://archive.raspbian.org jessie InRelease [14.9 kB]
Get:3 http://archive.raspberrypi.org jessie InRelease [22.9 kB]

...

npm notice created a lockfile as package-lock.json. You should commit this file.
added 166 packages in 81.166s
Removing intermediate container 13986530db28
 ---> 051eb94b8a3c
Step 19/20 : EXPOSE 9876
 ---> Running in 67b587845fe0
Removing intermediate container 67b587845fe0
 ---> 46973b7ba9ac
Step 20/20 : CMD ["npm", "start"]
 ---> Running in 153bf2ea02ad
Removing intermediate container 153bf2ea02ad
 ---> 6bf3d76d38ae
Successfully built 6bf3d76d38ae
Successfully tagged oliv-nodepi:latest
ed9a7d9042dddd3939b1788cf0e89d16f5273192a6456266507f072f90ce91bc
 $

Once the step above is completed, plug in your GPS, and run
 $ docker run -p 9876:9876 -t -i --privileged -v /dev/ttyUSB0:/dev/ttyUSB0 -d oliv-nodepi:latest
Then from a machine seeing the Raspberry PI on its network (it can be the Raspberry PI itself), reach http://raspi:9876/data/demos/gps.demo.wc.html in a browser.

This shows you the position the GPS has computed, and the satellites in sight.
You can also login to the image:
 $ docker run -it oliv-nodepi:latest /bin/bash

 #     #                                 ######    ###
 ##    #   ####   #####   ######         #     #    #
 # #   #  #    #  #    #  #              #     #    #
 #  #  #  #    #  #    #  #####   #####  ######     #
 #   # #  #    #  #    #  #              #          #
 #    ##  #    #  #    #  #              #          #
 #     #   ####   #####   ######         #         ###

 git version 2.1.4
 node:v9.11.1
 npm:5.6.0
 root@b9679d0d65a7:/workdir/node.pi#

... and do whatever you like.
The build operation needs to be done once.
There is no need to do it again as long as no change in the image is required.

Quick comment
So, with Docker, you do not deliver a software, you actually deliver an image (a virtual machine), on which a software is running.
This is indeed redefining the concept of portability that made Java and other JVM-aware languages so successful.
This may very well explain the rise of languages like Golang (aka Go).
It runs on my machine? Well, here is my machine! You can download and run it. Enjoy!

Saturday, March 17, 2018

Java Weather Station

This is a SwitchDocLabs SDLWeather80422 Weather Station, installed on the roof.

It is connected to a Raspberry PI A+, all the software is written in Java, no Python, no Arduino-like code, no C++.

There is an optional nodeJS server that runs on the Raspberry PI too, to enable WebSockets.

Find the core code here, and the example implementation here.

MySQL, PHP, Web Interface
Web-Components interface, pings the server every second.
WebSocket Web Interface, updated in real-time.
Some papers by John Shovic turned out to be very useful, specially in understanding what this debounce aspect is all about.

See it live here.

It even comes with a pebble application.

Sunday, September 10, 2017

Moving the Raspberry PI away from Swing

Rationale

This starts from a simple observation. A Raspberry PI can run on a boat, and consumes a very small amount of energy. It can do a lot of computations, logging, and multiplexing, among many others. It can run 24x7, without you noticing. It makes no noise, almost no light, and requires ridiculous amount of energy to run. Even a Raspberry PI Zero does this kind of job (for even less power), successfully.
One thing it is not good at is graphical UI. A graphical desktop is often too demanding on a small board like the Raspberry PI Zero. It becomes some times really slow, and cumbersome.
Running on it a program like OpenCPN seems absurd to me. Such a program runs fine on a bigger device, with several gigabytes of RAM available.
But, running a laptop 24x7 would be in many cases too demanding, specially on a sailboat, where everyone hates to run the engine ;)
I observed that at sea, I spend only a couple hours a day in front of the laptop, but it is often running by itself, doing some logging or calculations.
This is where it comes together, you could have a Raspberry PI Zero doing logging, multiplexing and what not, broadcasting require data on its own network (see the NMEA Multiplexer about that), then you would use a laptop whenever necessary, connecting on the Raspberry PI's network to get NMEA Data and more.
In addition, you can also use tablets and smart-phones, those devices know how to connect to a network, and have great rendering capabilities.
A problem is that writing a native application on those devices requires specific knowledge of the operating system, those skills are often redundant. iOS, Android, JavaFx, Swing all have UI rendering capabilities, but they're all totally different, and the learning curve for each of them is not always smooth.
A solution would be to write the UI part of the applications using HTML. Whatever OS runs on your laptop, tablet or smartphone (Windows, MacOS, iOS, Linux, Android, etc), you have a browser available, supporting HTML5 (if it does not, you should really upgrade it).
HTML5 and JavaScript have been gaining a lot of momentum in the recent years, new frameworks like jQuery, ionic, ReactJS, ...) appear every day, and provide really rich and nice UI.
My feeling would be to go down this route whenever possible, that would save a lot of efforts, and provide a pretty cool Graphical User Interface (GUI). I have written a lot of GUI in Swing. It would be now time to upgrade it. Re-writing them using JavaFX does not sound like the right choice. If I have to learn a new language to build a modern GUI, for now I'd rather use JavaScript and HTML5. This way, the same code runs whenever a browser exists... You have REST APIs available on the server (again, a Raspberry PI, even the Zero does the job well), and you use AJAX and Promises to get to them from the Web UI (WebSockets are also a realistic option, tested). The computation required to produce the payload returned by the REST services (often in json format) is easily supported by a Raspberry PI, and the complexity of the UI rendering is 100% taken care of by the browser, running on a more powerful device.

Implementation

To make sure all this is realistic, we have a REST implementation of a Tide Server, available here.
First, we have defined the REST Services, like
 /GET /tide-stations
 /GET /tide-stations/{station}
 /POST /tide-stations/{station}/wh?from=XXX&to=YYY
 /POST /tide-stations/{station}/wh/details?from=XXX&to=YYY
this is the easy part - and then an HTML5/JavaScript User Interface.


Harmonic coefficients are available for display


Period of time goes - in this UI - up to 1 month.


For one month, with harmonic coefficients, the volume of data transferred from the server is about 10Mb, it took about 14 seconds to get them.


In a most common case, it is around 25Kb.


This is running on a Raspberry PI, even a Raspberry PI Zero does the job without complaining.
There are a couple of challenges to address, JavaScript is not very well TimeZone equipped. But there are ways to get it to work.
That seems to be a viable approach.
Interestingly, even if we are trying here to address an energy problem - and not a budget one - a Raspberry PI Zero today cost just $10.

Saturday, December 31, 2016

NMEA Multiplexer, OpenCPN, GPSd...

I have been working on an NMEA Multiplexer that can run on small boards, like the Raspberry PI Zero. The code is available on github, see the documentation in the README.md.

It allows to mix all kinds of NMEA Sources into a single (or multiple) stream(s). You can read from Serial Ports, Log file(s), TCP, WebSocket, Sensors (like BME280, HTU21DF, LSM303, etc), merge those data and rebroadcast them on Serial port, TCP, Log file, WebSocket, GPSd, etc. UDP is being worked on.

Data can also be computed and injected in the output stream, like True Wind, Current direction and speed, etc.

As a graphical desktop can be cumbersome on small boards, the Multiplexer comes with a tiny HTTP server that provides a Web UI and REST services to allow remote Admin.

It also comes with several demos and samples
This all works just fine with OpenCPN, SeaWi, that can take TCP streams as NMEA Data Input.
I was also wondering about GPSd. I had some mixed feelings about it. Mostly, I was asking myself "Why should I parse GPSd json objects if I can parse NMEA Sentences?", and could not find any satisfying reason. The topic is mentioned on the GPSd web site's FAQ pages, but nothing clear (to me) came up from that.
Interestingly, OpenCPN can also take GPSd streams as input. But there is a trick.
The first GPSd exchange begins with a ?WATCH request. It is followed by a JSON Object like this:
  ?WATCH={"enable":true,"json":true}
... and here is the trick, OpenCPN sends a
 ?WATCH={"enable":true,"nmea":true}
This nmea option is "poorly" documented, but very useful. Instead of sending JSON objects, GPSd spits out the raw NMEA sentences, as they were read. Then GPSd is just a regular TCP stream, and OpenCPN already knows how to parse the NMEA sentences it delivers. This way, GPSd is not limited to strictly GPS-related sentences. It can convey all NMEA sentences, Boat Speed related, Wind related, etc. This is what the GPSd forwarder that comes with the Multiplexer is doing.
Happy Streaming, happy new year!

Sunday, July 24, 2016

Live Wallpaper, offline

The Live Wallpaper (in the navigation console) has been improved. Several bugs were fixed (like the one for the daylight), and you can now use it offline, like when no NMEA data are coming. This can be useful when you are not on the boat (like at home).

You can give a default position (in the preferences), and it will be used when no GPS Data is available.
New features:
  • The tilt is based on the Sun declination
  • You can have Moonlight and Sunlight
  • The tide curve of the closest station is displayed (closest in a radius of 100 nautical miles)
  • Sun and Moon positions are displayed (when the body is visible)
Code and (some) doc are available on GitHub.