The CoffeePi (Part 2 of 2)

Breaking news!

The CoffeePi will be appearing at Smart IoT London 2016!
smart-iot-london

Feel free to drop by our booth and get a hot beverage from the CoffeePi served using Nabto!

Back to the story

Please read Part 1 to read about the preliminary steps in the coffee saga.

This part will be dealing with the following points

  • Figuring out how to wire up and emulate the rotary knob
  • Adding the Nabto framework
  • Making the full menu available
  • Order a cup of coffee in London, trigger instant brewing in Denmark

The rotary knob

The rotary knob has three pins as seen in the image below

no_finger.png

The backside of the rotary knob. We see the three pins, the center being common high and the two outer pins which go high or low according to the rotation of the knob

The center pin is common high and the outer pins output the necessary encoder pulse needed for the main board. To get an idea of how these pulses look we checked it out using a logic tester

20160222_131353.jpg

The logic tester in use

which gave an output like this

logic

The output from the logic tester. The upper section is the output for moving to the left and the bottom section is the output for going right.

The upper section, in the image above, shows the output from the rotary knob when turning the knob counterclockwise which if equivalent to going  left on the main board display. Likewise the bottom section shows the clockwise rotation which result in a right movement on the main board display.

From this we see that the direction the knob is turned can be directly translated into which direction we are moving on the main board display simply by relating which pins changes state first. In other words, to move left/right we need to emulate an output like the top/bottom one seen in the image above.

Before doing that, we need a common starting point, meaning that we need to know if the pins are high or low to begin with. The simplest way to control this was to cut the pins like this

rotary_knob_pinout

The two switches represent two optocouplers. This means that we can disable the manual rotary knob controls by switching a pin on our Raspberry Pi. Doing that results in the receiving end of the pins to be pulled low. We thus have our starting point.

In total, our wiring should now look something like this

total_wiring

Wiring diagram for the CoffeePi. In total 10 optocouplers were needed, 6 for the buttons and 4 for the rotary knob. Common high, H, from the CoffeePi and common ground from the Raspberry Pi.

As can be seen from the wiring diagram above the 6 OCs on the left side controls the 6 buttons and the 4 on the right hand side controls the rotary knob. We input a digital high/low value on the bottom which signals a certain output on top, to the coffee machine.
The resistors are 270Ω, common ground is from the Raspberry Pi and H is common high from the CoffeePi (the blue markings in this image from The CoffeePi (Part 1 of 2)).

When the dis. pin is set high the rotary knob works in its normal manual way. When we set it low, the black inputs (generated from manual rotation of the knob) are disabled and we can instead send our own pulses using Rot.1 & 2.

For reference, the wiring looks like this in real life

IMG_20160317_122230 - Kopi

Wiring for the CoffeePi in real life. Notice the two extra optocouplers in the middle which are not hooked up for any output.

As always, the real projects end up being messier than on paper but both images have the same layout: 6 OCs for the buttons on the left and 4 OCs for the rotary knob on the right.

Adding the Nabto framework

Since our platform is the Raspberry Pi (Linux) I suggest checking out Raspberry Pi 3 IoT, perfect for Nabto for instructions on how to get the uNabto software up and running in no time. After that please check out The SunPi control center to get an idea of how we get a browser to communicate with our uNabto software.
For now we only need to worry about unabto_application.c in the src folder.

Making the full menu available

In The CoffeePi (Part 1 of 2) we were only able to progammaticrally push a button after we manually turned the rotary knob to the correct position. Since we now have an understanding of how the rotary knob creates pulses we can now make the full menu available. This is done in the following few steps (code snippets taken directly from unabto_application.c)

Disable manual control

// Shut off manual control
digitalWrite(11, LOW);
delay(wait_msec);

As well as disabling manual control from the rotary knob, the two pins are pulled low such that we always have the same initial setting.

Get a starting point

Since we have 9 available items on our menu we begin by going 8 steps to the left

// Go all the way to the left
for (i = 0; i < 5; i++){

    digitalWrite(13, HIGH);
    delay(wait_msec);
    digitalWrite(14, HIGH);
    delay(wait_msec);
    digitalWrite(13, LOW);
    delay(wait_msec);
    digitalWrite(14, LOW);

    delay(wait_msec);
}

This is done to ensure that we always have the same starting point when getting to the next step.

Selecting desired product

All our pins are now low and it is finally time to go to the desired product. Each item has a certain number associated with them (from the radio buttons) which directly corresponds to how many steps we need to move to the right.

html_page

The CoffeePi is up and running!

The most popular choice is, of course, Coffee and thus it is pre checked when accessing the CoffeePi online. This button has a value, or id, of 3 so when we click Brew the number/id is send using a Nabto request.

// Go id amount of steps to the right to the desired item
for (i = 0; i < id; i++){
    // If odd
    if (i % 2 != 0){
        digitalWrite(14, LOW);
        delay(wait_msec);
        digitalWrite(13, LOW);
    }
    else{
        digitalWrite(14, HIGH);
        delay(wait_msec);
        digitalWrite(13, HIGH);
    }
    delay(wait_msec);
}

After that bit we should now be at the desired item, and we can now emulate a button press

// Push button
digitalWrite(10, LOW);
digitalWrite(10, HIGH);
delay(100); // 0.1 sec
digitalWrite(10, LOW);

The item should now be brewing!

Clean up

While our lovely hot beverage is being brewed we send a few extra commands. First, we ensure that the two pins controlling the pulses are being set low again and finally, we turn on manual control of the rotary knob again.

// Set the steppers to low
digitalWrite(13, LOW);
digitalWrite(14, LOW);

// Turn on manual control
digitalWrite(11, HIGH);

Remarks

Since we started using a synchronous event handler, the Nabto framework expects to get a response in just 10 msec – so we need to run all this pin switching in a separate thread. The thread is set to being detachable, such that it will self terminate when all code inside the thread has been executed. Please see the appropriate code. In a later post, we will show how to use an asynchronous approach instead and save this separate thread.

From London with love

What better way to demonstrate the true IoT this coffee machine has now become by ordering a cup of coffee from London and then seeing it being brewed in Denmark a few seconds later?

Notice how my colleague in London is laughing through the process!

If you suddenly got the urge to create your own IoT device using Nabto feel free to check out nabto.com and sign up for a developer account portal.nabto.com, it is all free and you can create and manage 10 devices. This is also where you can find the SDKs and other Nabto software!

The full code for the CoffeePi can be found right here.

ESP8266 WiFi Module + Nabto

This post is outdated. Please have a look at the updated version incorporating our new AppMyProduct platform.

The ESP8266 is a low-cost WiFi module that can be programmed directly like a microcontroller. Already thinking of your next Internet of Things project?

While an available Arduino library allows a quick start, there is still one problem to overcome: How to access your ESP8266 from outside your home network without nerve-racking router and firewall configurations or heavy and intransparent cloud services? Running the uNabto server on your ESP8266, you can establish a fast and secure Peer-to-Peer connection using only a static ID – from everywhere, no matter what is in between.

What hardware you’ll need

IMG_20160303_153803

Adafruit HUZZAH ESP8266 Breakout

IMG_20160303_153830

USB to TTL Serial Cable

This project is tested on an Adafruit ESP8266 board. It’s not the cheapest you can get, but very prototyping friendly. You can put it on a breadboard and it has a 3.3V voltage regulator onboard. Of course, you can also use a different ESP8266 module. Wikipedia provides an extensive list of available modules.

Regarding the USB to TTL Serial Cable (get it e.g. here), there are no special requirements when using the Adafruit module. If you use a different module, make sure the voltage levels match, since most boards only accept 3.3V.

Solder the pin header to your ESP8266 board and connect it to your USB to TTL adapter using 4 wires:

wiring

What software you’ll need

This project is tested on Ubuntu 15.10 but should work on any OS supported by the Arduino IDE.

We want to program the ESP8266 directly, instead of using any higher level interpreters available for the module. Adafruit provides a nice tutorial on how to setup your  Arduino IDE accordingly.

If everything is running, you should be able to compile the following simple sketch and upload it to your ESP8266. This will make the onboard LED blink every second.

const int led = BUILTIN_LED;

void setup() {
  pinMode(led, OUTPUT);
}

void loop() {
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
}

How the Nabto platform works

So far, so good. But how does the Nabto platform actually work? The drawing below gives a brief overview. Your ESP8266 module represents the Device running the uNabto server. As soon as it connects to the internet it identifies itself at the Nabto Basestation, using its unique ID. If a Client wants to connect to the ESP8266, a connect request with the ID is sent to the Basestation, and a direct connection to the device is established. A client can be an HTML page running in a desktop browser extension (IE, Firefox) or the Nabto Mobile App (iOS, Android), or a custom Nabto API Client.

nabto-platform-basics

Get more information on the Nabto platform and the Client/Device SDKs on developer.nabto.com.

The uNabto Platform Adapter

The uNabto server is divided into two layers:

  • The actual uNabto framework (uNabto SDK)
  • The uNabto Platform Adapter abstraction layer between the framework and the Native Platform

unabto-platform-adapter

Hence, we only need to implement the uNabto Platform Adapter, in order to port the uNabto server to the ESP8266 module.

Implementing the Platform Adapter

The Platform Adapter acts as link between the generic uNabto framework and the Arduino platform, including the ESP8266 WiFi library. The adapter is divided into single files, as suggested in the Nabto documentation (TEN023 Writing a uNabto device application, chapter 12):

  • unabto_config.h: Basic uNabto configuration
  • unabto_platform_types.h: Define all necessary uNabto types
  • unabto_platform.h: Platform specific ad-hoc functions
  • network_adapter.cpp: Init, close, read and write functionality for network data
  • time_adapter.cpp: Time functions
  • dns_adapter.cpp: DNS resolving
  • random_adapter.cpp: Random generator
  • log.cpp: Logging

If you are interested in how the platform adapter is implemented in detail, check the adapter files in the src directory of the library on GitHub.

Using the Library

Get the Nabto ESP8266 Arduino library from https://github.com/nabto/unabto-esp8266-sdk/tree/v1.1 and place it in your Arduino library directory. If you don’t know where your library directory is located, see the guide on manual installation of Arduino libraries.

After restarting your IDE the library is installed. An example sketch can be found in

File -> Examples -> Nabto-ESP8266 -> LightSwitch

The sample sketch includes the Nabto class, which encapsulates the Nabto setup. First, some settings are made. This includes the WiFi SSID and password, followed by the unique Nabto ID and preshared key of the device, as well as the pin of the onboard LED to be controlled.

#include <Nabto.h>

// Enter ssid and password of your WiFi network
const char* ssid = "...";
const char* password = "...";

// Enter device id and preshared key from developer.nabto.com
const char* nabtoId = "...";
const char* presharedKey = "...";

// Specify LED pin
const int led1_pin = BUILTIN_LED;

The setup function is used to init the LED pin and the Serial module. In line 42 you can see how the Nabto module is initialised. The begin(..) function is blocking, therefore, the following printout of the Nabto version number only takes place, if the WiFi connection was established.

void setup() {
  // Initialize built-in led
  pinMode(led1_pin, OUTPUT);
  digitalWrite(led1_pin, 1);

  // Initialize Serial
  Serial.begin(115200);

  // Initialize Nabto
  Serial.println("Init...");
  Nabto.begin(ssid, password, nabtoId, presharedKey);

  // Optionally get nabto firmware version
  char versionString[10];
  Nabto.version(versionString);
  Serial.print("Nabto v");
  Serial.print(versionString);
  Serial.println(" running...");
}

The only thing that needs to be done in the loop function is to call the tick() method of the Nabto class. This triggers the framework to check for new UDP packets and send responses. The time between ticks should be around 10 milliseconds. This is achieved by a hard delay, but you can also use the time to do application related stuff.

void loop() {
  // Check for new nabto udp packets and send response. Non-blocking
  Nabto.tick();

  // We have chosen to sleep 10 milliseconds between tics
  delay(10);
}

The following two functions provide a convenient way to set and read the LEDs, although we will only use one LED in this example.

// Set LED and return state.
// Only using ID #1 in this simple example
uint8_t setLed(uint8_t led_id, uint8_t led_on) {
  if (led_id == 1) {
    // inverted
    digitalWrite(led1_pin, !led_on);
    return !digitalRead(led1_pin);
  }
  else {
    return 0;
  }
}

// Return LED state.
// Only using ID #1 in this simple example.
uint8_t readLed(uint8_t led_id) {
  if (led_id == 1) {
    // inverted
    return !digitalRead(led1_pin);
  }
  else {
    return 0;
  }
}

The actual handling of received Nabto messages from the client is implemented in the application_event(..) function. The handler uses the message format used in the default HTML Device Driver, provided in the Nabto portal. For more information on how to create your own HTML DD, please refer to TEN024 Writing a uNabto HTML client.

application_event_result application_event(application_request* appreq, unabto_query_request* r_b, unabto_query_response* w_b) {
  switch(appreq->queryId) {
  case 1:
    {
      //  <query name="light_write.json" description="Turn light on and off" id="1">
      //    <request>
      //      <parameter name="light_id" type="uint8"/>
      //      <parameter name="light_on" type="uint8"/>
      //    </request>
      //    <response>
      //      <parameter name="light_state" type="uint8"/>
      //    </response>
      //  </query>

      uint8_t light_id;
      uint8_t light_on;
      uint8_t light_state;

      // Read parameters in request
      if (!unabto_query_read_uint8(r_b, &light_id)) return AER_REQ_TOO_SMALL;
      if (!unabto_query_read_uint8(r_b, &light_on)) return AER_REQ_TOO_SMALL;

      // Set light according to request
      light_state = setLed(light_id, light_on);

      // Write back led state
      if (!unabto_query_write_uint8(w_b, light_state)) return AER_REQ_RSP_TOO_LARGE;

      return AER_REQ_RESPONSE_READY;
    }
  case 2:
    {
      //  <query name="light_read.json" description="Read light status" id="2">
      //    <request>
      //      <parameter name="light_id" type="uint8"/>
      //    </request>
      //    <response>
      //      <parameter name="light_state" type="uint8"/>
      //    </response>
      //  </query>

      uint8_t light_id;
      uint8_t light_state;

      // Read parameters in request
      if (!unabto_query_read_uint8(r_b, &light_id)) return AER_REQ_TOO_SMALL;

      // Read light state
      light_state = readLed(light_id);

      // Write back led state
      if (!unabto_query_write_uint8(w_b, light_state)) return AER_REQ_RSP_TOO_LARGE;

      return AER_REQ_RESPONSE_READY;

    default:
      return AER_REQ_INV_QUERY_ID;
    }
  }
}

Test your device

After compiling and uploading your LightSwitch sketch to the ESP8266, it establishes a connection to your WiFi network and starts the uNabto server. In your serial monitor you should see the following printout:

Init...
Device id: 'mydeviceid.demo.nab.to'
Program Release 2.21889
Application event framework using SYNC model
SECURE ATTACH: 1, DATA: 1
NONCE_SIZE: 32, CLEAR_TEXT: 0
Nabto was successfully initialized
Nabto v2.21889 running...
SECURE ATTACH: 1, DATA: 1
NONCE_SIZE: 32, CLEAR_TEXT: 0
State change from IDLE to WAIT_DNS
Resolving dns: mydeviceid.demo.nab.to
State change from WAIT_DNS to WAIT_BS
State change from WAIT_BS to WAIT_GSP
######## U_INVITE with LARGE nonce sent, version: - URL: -
State change from WAIT_GSP to ATTACHED

When entering you device ID into your browser or Nabto App, you can see the uNabto Demo client. Using the light switch you can now turn the built-in LED on and off from everywhere!

Screenshot_2016-03-05-14-50-37

Future improvements

Currently, the WiFi SSID and password, as well as the device ID and the preshared key are stored in the ESP8266’s flash memory. This requires an update of the source code and a firmware upload on every change of these parameters. A possible solution to this problem could be a very small web server running on the ESP8266, which is accessible through a parallel running WiFi access point. The parameters entered through the web interface could then be persistently stored in the EEPROM.

Raspberry Pi 3 IoT, perfect for Nabto

A few days ago (29/2-2016) the new Raspberry Pi 3 was announced. Of course we were all excited here at the Nabto headquarters and quickly bought a few.

Since they are reviewed as the perfect platform for IoT we wanted to check out if it is perfect for Nabto as well. Spoiler alert: it is !

Setting up the Pi 3

The fastest way to get wifi and Nabto up and running on your Pi 3 is to burn an image to your sd card (for this post we are using Raspbian Jessie Lite). After doing that, hook up your Pi3 by wire to your local network. You can now access the Pi, either directly by HDMI and a keyboard or over SSH.

One of the main features of the new Pi3 is the onboard wifi module so the first thing to do is to search for available networks and make the Pi autoconnect to the one we want. This is most easily done by issuing the following commands one line at a time

wpa_cli
scan
scan_results
add_network
set_network 0 ssid "ssid_name"
set_network 0 psk "password_stuff"
enable_network 0
save_config
quit

Where you should, of course, replace ssid_name and password_stuff with the SSID and password of the network you are trying to connect to.
After that you can reboot the Pi and remove the wire and you have a Raspberry Pi 3 ready for IoT!

Setting up Nabto

Setting up Nabto is as easy as setting up the wifi. First of we need to get the necessary tools for getting the uNabto files and compiling for the Raspberry Pi. This is done by issuing the following commands one line at a time

sudo apt-get install git
sudo apt-get install cmake
git clone https://github.com/nabto/unabto.git
cd unabto/apps/raspberry_pi
cmake .
make

We now have Nabto compiled on our Pi!
All that is left to do is to create a new device at portal.nabto.com. Simply Add Device and copy the newly created Key 

We now return to the Raspberry Pi and issue the following command for initiating the Nabto software

sudo ./unabto_raspberrypi -d "id".demo.nab.to -s -k "key"

You should see a couple of lines of output ending with

13:40:47:548 unabto_attach.c(575) State change from WAIT_GSP to ATTACHED

Which means Nabto is successfully up and running!

Trying out Nabto

Now that everything is up and running the final thing to do is to access id.demo.nab.to in your browser. You will be met with a log in page, simply click Guest, followed by an image like this

html_dd

The uNabto demo is up and running!

Sliding the switch to either side will now trigger the onboard activity light on your Raspberry Pi, check it out!

For a more in depth introduction on how to write your own functionality into the Nabto framework, please refer to this blog post The SunPi control center.

The CoffeePi (Part 1 of 2)

When I asked if I could hack the 1300$ (8800 dkk) coffee machine at the Nabto headquarters the responses varied from “no way” to “I’ll give it 30 % chance of success”. Eventually they surrendered to my request, so let’s see if it all worked out!

Since this project was rather substantial, the coffee machine saga will be split in two (possibly three later on) parts.

In this part we will be dealing with

  • Disassembling the coffee machine and finding points of interest
  • Figure out the what is needed to control the buttons
  • Brew an actual cop of coffee using SSH.

Part 2 will deal with

  • Figure out how to wire up and emulate the rotary knob
  • Adding the Nabto framework
  • Making the full menu available
  • Order a cup of coffee in London, get it seconds later in Denmark

Disassembling the coffee machine

before_dismantling.png

The starting point, a shiny functioning Siemens EQ 7 Plus coffee machine

The starting point was the Siemens EQ 7 (TE712201RW) coffee machine, as seen in its standard form in the image above.

First of I had to decide whether to try and access the three pin service port or to rip the machine apart and make some proper hacking. Since I found no information about this service port online I decided on the latter (plus it sounded like a lot more fun).

Machines like these are built with as few screws as possible and thus all side panels are hold in place by small plastic pins. Furthermore the machine is made such that to get to the main board you have to remove the back panel, then the side panels and finally the front panel. In total, dismantling the coffee machine was not easy but I did it MANY times in the process because of broken soldering or crushed wires.

20160218_120943

E-waste or successful hack?

With the front finally of it was time to have a look at the main board.

20160218_121202

The main board inclosure

We see 6 buttons and a rotary knob in the middle. Now we just need to check out what is underneath.

Controlling the buttons

20160218_121542 - marked.jpg

The main board of the coffee machine.

Using a multimeter I began by figuring out any common connections indicated by the blue lines in the above image.

When one of the buttons are pushed a connection is made between the blue and yellow side of the button. We want to be able to create artificial button pushes and thus we need to solder on wires at every yellow line in the above picture and a common blue wire.

20160223_194222.jpg

Strapped up for the party

We can now imitate a button push by simply shortening common with any of the buttons.
To control this programmatically I went with optocouplers, specifically Fairchild 817 chosen because it has a high CTR min. meaning that we can directly activate them using the 3.3V digital pins from a Raspberry Pi, as seen below.

20160222_165956.jpg

Using an optocoupler directly from the 3.3V pins from the Raspberry Pi.

I chose optocouplers since they are basically “light relays” as my colleague said.

opto

Cross-section through an optocoupler.[wiki] As can be seen the red LED is electronically isolated from the green sensor. Thus the two sides can have very different voltage levels without damaging anything.

This turned out to be a good choice since the logic of the coffee machine runs at 5V and the Raspberry digital pins run at 3.3V, as mentioned earlier.

All that is left is then to hook up the main board again and follow the on screen instructions:

20160218_145749

Please close the door!

After “closing the door” we need to mark the wires such that we know what they do.

20160218_155624

Almost assembled and soon labeled.

I simply shorted each wire with the common wire (see above) to figure out the function of each wire.

20160218_181952.jpg

Wires from coffee machine ready to rock

As seen above the wires are now coming out of the coffee machine in a nice little bundle. We now simply need to wire up alle the optocouplers to the raspberry pi and when that is done connect everything together.

20160222_161923

Heating the soldering iron.

Since I did not have any connectors lying around I had to create some using a bit of soldering.

20160222_172341

The optocouplers all wired up.

To avoid damaging the optocouplers (and RPi) I inserted a 270Ω resistor alongside each. The “red” wire above is common ground and the numbered “green” wires are the wires we can digitally set high/low. When we set an optocoupler high it means that power is allowed to flow through on the right hand side in the image above, i.e. a button on the coffee machine is pushed.

Have a cuppa

We can now finally wire everything together such that we can click any of the six buttons by issuing a simple command over SSH:

gpio write 10 1
gpio write 10 0

This basically emitates pushing the button in (first line) and then releasing it again (second line).

So far we still have to manually scroll to the desired item in the menu, but when we are there we can programmatically push the button, as seen below:

20160222_184911

The first cup of coffee ordered remotely (i.e. 5 meters away at my computer)

Great success! 

Issues

As mentioned, we still have to manually scroll to the desired menu item before we can programmatically push a button.

The next part will be dealing with this problem as well as a few others:

  • Figure out how to wire up and emulate the rotary knob
  • Adding the Nabto framework
  • Making the full menu available
  • Order a cup of coffee in London, get it seconds later in Denmark

 

Security in Nabto P2P/IoT solutions

Security in IoT and especially in home security solutions has been subject for several recent articles and debate, for instance see http://thenewstack.io/snooping-webcam-reveals-security-dangers-internet-things/.

Since the article above covers the general security issues of P2P, the same concerns of course apply to Nabto based solutions – this post addresses these concerns and summarizes the security principles of our platform, some of it applies to P2P solutions in general.

Basically, to allow a peer-to-peer connection to be established to a device, such as a camera, the camera must communicate with a central service that knows about the camera’s network configuration. This is not any different than in e.g. IP telephony where the IP phone central knows about each IP phone’s network configuration and needs to communicate periodically with each IP phone to allow other peers to make calls to it:

When a Nabto enabled device (e.g. a P2P IP camera) is turned on, it will try to register itself with its associated central services. Our approach to this is to use DNS – each Nabto enabled device has an associated DNS hostname, for instance <some-id>.p2p.vendor.net. This DNS name resolves to the Nabto “phone central” services, we denote this the “Nabto basestation”:

nabto-devices-white

The registration with the basestation takes place using strong cryptography using HMAC/SHA256 and AES128 with a per device unique shared secret. This allows a secure, private channel to be setup between the basestation and the device; all subsequent remote communication with the device is then encrypted for confidentiality and integrity. This approach without the need for asymmetric cryptography on the device enables Nabto to work on even the most resource constrained devices, e.g. sub 1-dollar 8-bit MCUs.

The client that communicates with the device is authenticated through an RSA X509 certificate. When a client initiates a connection towards a device, a secure channel is first established between client and basestation using a regular RSA based TLS handshake. A session key is then established and exchanged between client and device, along with IP information to allow a P2P connection attempt.

Once a connection is established, the device owner controls who accesses the device, the traffic cannot be manipulated and an attacker cannot intercept the communication.

nabto-security

This is all good as long as you can trust the owner of the basestation and that what I said above is actually true about the device code. The Nabto platform allows vendors to host their own private basestation – and most of our biggest customers indeed do that today. This means that Nabto is completely out of the loop. And that the vendor can have their servers located in their desired geographical region – so no need for communication with seemingly random hosts in e.g. China. The vendor can hence have a trust relationship solely with their customers (the end-user), the end-user sees no peculiar traffic between their device and an unknown 3rd party.

Our device SDK is open source, you can download everything on Github so you can see exactly what the communication is about. Of course this is not a guarantee – the individual vendor could in principle change the source code. But if you inspect the communication  with e.g. Wireshark and correlate with the available source code, the task for understanding the individual vendor’s product for an analyst is indeed simpler.

With all the above being said – much of the current discussion about P2P security is about the owner of the device not being able to turn P2P access off: It is of course up to the vendor to control how to activate the Nabto P2P functionality – but we make it simple to do so, we have a single “master switch”; if not turned on, there is absolutely no P2P related communication taking place.

For more information on security in the Nabto platform, don’t hesitate to contact us on support@nabto.com or take a look in our security guide TEN036 Security in Nabto Solutions.

Blog launched!

Last week we launched our blog, something we have wanted for a long time: A place to share thoughts from the team as well as cool projects realized using the Nabto platform. In the first such post, Marcus describes how he provided his solar cell project with remote access in a few simple steps using Nabto.

Don’t hesitate to contact us if you have some good ideas for a project to write about or implement here! Or if you already have made a cool Nabto enabled project, let us know and we will be happy to write about it! Use the chat on www.nabto.com or write to support@nabto.com.

Ulrik and the rest of the Nabto team

The SunPi control center

Ever since I first build my solar powered Raspberry Pi system, called the SunPi, I wanted to be able to remote control it.

More specifically, in the summertime, when the sun shines heavily the battery would be filled within an hour after sunrise. The rest of the day, the charge controller would simply waste/curtail excess energy by dumping it as heat.
Instead of doing that I wanted to use this energy for something. Specifically I wanted to be able to remote control a relay such that I could activate whatever device I had lying around.

total_overview

Overview of the SunPi system

To determine whether or not to activate the relay I had to be able to read the voltage level which is equivalent to how filled the battery is. I did this using a INA219 current sensor, some Python and plotted it here. But I really wanted to have everything on a single page such that I could quickly determine whether or not to activate the relay. I wanted to be able to access this control center from anywhere and in a secure way. With Nabto I found the solution.

How Nabto works

nabto_overview

Overview of the Nabto framework

As seen in the above figure the client side (e.g. the device you are reading this on) has HTML, CSS and JavaScript running when you visit the SunPi control center. Altering a slider in the HTML calls a JavaScript function which in turn sends a Nabto request to the device side of things.
In this case the device is a Raspberry Pi running some compiled C code. For our power and voltage readings (more below) a Python script is called from within the C code.
That is basically all there is to the framework.

To get a better feel of how to add functionality I will walk through

  • Controlling a GPIO pin
  • Retrieving data

Note that these examples build on the default html_dd (Client side) and this RPi demo (Device side).

Controlling a GPIO pin

HTML

We start by creating a slider with a unique id (rgb-r in this case) containing the OFF and ON options.

<li>
  <h2>Red</h2>
  <div class="ui-li-aside">
    <select id="rgb-r" data-role="slider">
      <option value="off">OFF</option>
      <option value="on">ON</option>
    </select> 
<li>>

JavaScript

When the slider with the rgb-r id is toggled, the accompanying JavaScript-script is activated.

$("#rgb-r").change(function(){
  var state = $(this).val() === "off"?0:1;
  jNabto.request("light_write.json?light_id=1&light_on="+state, setLight_r); 
}); 

Where the setLight_r function shifts the actual slider.
What is perhaps more interesting is the jNabto.request part. The jNabto requests are defined in the unabto_queries.xml file and the light_write.json used above look like this

<query name="light_write.json" description="Turn light on and off" id="1">
  <request>
    <parameter name="light_id" type="uint8"/>
    <parameter name="light_on" type="uint8"/>
  </request>
  <response format="json">
    <parameter name="light_state" type="uint8"/>
  </response>
</query>

As seen, the request sends the two light_id and light_on variables containing information about which pin/light we are dealing with and which state (light_on) we want it in. After this, we expect to receive a json format response, specifically the light_state the pin has been set to. We notice that the query id is 1.

C code

On the device side we arrive at case 1 (in unabto_application.c) since the light_write.json has id = 1.

case 1: {
    uint8_t light_id;
    uint8_t light_on;
    uint8_t light_state;

    // Read parameters in request
    if (!buffer_read_uint8(read_buffer, &light_id)) {
        NABTO_LOG_ERROR(("Can't read light_id, the buffer is too small"));
        return AER_REQ_TOO_SMALL;
    }
    if (!buffer_read_uint8(read_buffer, &light_on)) {
        NABTO_LOG_ERROR(("Can't read light_state, the buffer is too small"));
        return AER_REQ_TOO_SMALL;
    }

    // Set light according to request
    light_state = setLight(light_id, light_on);

    // Write back pin state
    if (!buffer_write_uint8(write_buffer, light_state)) {
        return AER_REQ_RSP_TOO_LARGE;
    }
    return AER_REQ_RESPONSE_READY;
}

Most of this is for error logging, we only need to focus on the setLight function and how we plan on sending a message back to the client side afterwards.
The setLight function looks like this

// Set GPIO pin and return state,
uint8_t setLight(uint8_t id, uint8_t onOff) {
    theLight[id] = onOff;

    NABTO_LOG_INFO(("Nabto: %s turned %s!\n", pin_name[id], on_off[theLight[id]]));

#ifdef __arm__
    /* Toggle GPIO pins on Raspberry Pi	*/
    //Change pin output according to id and theLight state

    if (theLight[id]){
        //Activate pin
        digitalWrite(pin_id[id], LOW);
    }
    else if(theLight[id]==0){
        digitalWrite(pin_id[id], HIGH);
    }
#endif

    return theLight[id];
}

Where we toggle the chosen pin on or off depending on the light_on variable passed from the client.

When we sucessfully set the actual pin we write back the pin state to the client using the buffer_write_uint_8 command. And that is bascially all you need to control a GPIO pin on the Raspberry Pi using the Nabto framework.

Retrieving data

HTML

The HTML code for retrieving data is basically just a button which signals the JavaScript to do a certain task, in this case we are dealing with id=”ina_update” (remember, we are using a INA219 current sensor).

<li>
  <input type="button" id="ina_update" data-icon="refresh" value="Read Voltage and Power"/>
</li>

JavaScript

The accompanying JavaScript function look like this

$("#ina_update").click(function() {
  queryINA219($(this));
});

where

function queryINA219(input) {
  jNabto.request("ina_data.json?", function(err, data) {
    if (!err) {
      temp_power = data.power_w/10000

      // Check if negative
      if (temp_power > 100)
      {
        temp_power = temp_power - 200
      }

      input.val("Voltage: " + (data.voltage_v/10000).toFixed(2) + "V, Power: " + temp_power.toFixed(2) + "W").button("refresh");
    }
  });
}

contain the ina_data.json jNabto request. Again we check the unabto_queries.xml file and make sure that

<query name="ina_data.json" description="Read voltage and power status" id="3">
  <request>
  </request>
  <response format="json">
    <parameter name="voltage_v" type="uint32"/>
    <parameter name="power_w" type="uint32"/>
  </response>
</query>

the ina_data.json query id is 3.

C code

The request is sent to the device side where we end up in case 3 because the ina_data.json request has id = 3.

case 3: {
    // Get voltage from INA219
    getINA219_data(&voltage, &power);

    NABTO_LOG_INFO(("Nabto: Read voltage=%f and power=%f\n", voltage, power));

    // Write back data
    if (!buffer_write_uint32(write_buffer, voltage*10000)) 
    {
        return AER_REQ_RSP_TOO_LARGE;
    }

    // Prepare for negative numbers. This will be converted back in the html_dd app.js file
    if (power<0)
    {
        power = power + 200;
    }
            
    // Write back data
    if (!buffer_write_uint32(write_buffer, power*10000))
    {
        return AER_REQ_RSP_TOO_LARGE;
    }
    return AER_REQ_RESPONSE_READY;
}

As seen above, the power data needs special preparation since we are writing uint32 (unsigned, i.e. numbers are always positive). When the battery charges the power is defined to be positive and when it discharges it is of course negative. Since my solar panel has a maximum rated power of 100W (which it never reaches) and my maximum power consumption is 10W at any given time, I simply add 200 to the power measurement. I made sure to undo this addition in the accompanying JavaScript as seen above (// Check if negative).
Finally we take a look at the getINA219_data function,

// Get INA219 data
void getINA219_data(float* voltage, float* power){

    FILE *fp;
    char path[1035];
    /* Open the command for reading. */
    fp = popen("sudo python path/to/ina219_python_c.py", "r");

    if (fp == NULL) {
        NABTO_LOG_INFO(("Failed to run Python script\n"));
        exit(1);
    }
    /* Read the output a line at a time - output it. */
    int k = 0;
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
        k = k + 1;
        if (k==1){
            *voltage = atof(path);
        }
        else if(k==2){
            *power = atof(path);
        }
    }
    /* close */
    pclose(fp);
}

The function calls a Python script which print out two lines of data. The lines contain the voltage and the power flowing in or out of the SunPi battery, respectively.
The data is then sent back to the client side using the buffer_write_uint32t command as seen above.
These are the building stones for how to write a simple Nabto application. After expanding on this a bit I finally had my control center.

The SunPi control center

control_center

The control center enables the user to control a RGB LED as well as a single relay or retrieve the voltage and power flowing into (or out) of the SunPi battery. It is also possible to retrieve the internal temperature of the SunPi.

Thus I can now simply access the Nabto SunPi control center (just click on guest to try it out. NOTE: no longer available) and then check the voltage. The battery is full when the voltage is above ~13V. If that is the case I can activate the relay or use the extra power for an RGB LED.

The full code is available on Github.

That’s all!