Monday 29 May 2017

Tutorial - using Amazon Dash with a Pi Zero and node.js

Introduction

In MagPi Magazine (issue 57) there was an article about how you can subvert an Amazon Dash button and use it as a Internet of Things ("IoT") button. However, the code in the article had several syntax errors. Once I fixed the syntax errors I still couldn't get it to work with my button. Then I found that a key ingredient, tcpdump (needed by scapy), was missing - so I installed that too. I ended up with some working code but it wasn't very reliable, especially using wireless on the Raspberry Pi Zero W. After doing a bit of research and experimentation, I got it working better by using "dasher", a node.js script.

Node.js is a server-based runtime environment for executing JavaScript code. It allows non-blocking multi-threading applications to be deployed. This is a fancy way of saying that you can leave it running in the background on your computer (Raspberry Pi in this case) and it will just sit there listening until something triggers it (without consuming lots of processing power).

A companion application, NPM, is a package manager for node.js scripts.

As in the MagPi article, dasher would allow the Dash button to toggle an IoT bulb such as the Lifx or Philips Hue. I don't have one of those so I'll use a simple LED and then move on to IFTTT. Rather than tie up a Raspberry Pi 3, I thought this would be a good use for the cheap-as-chips Raspberry Pi Zero W. Incidentally, although this works well on a Pi Zero W, it doesn't seem to be very reliable using a basic Pi Zero with a wireless dongle attached to the USB port. If you've only got a non-wireless Pi Zero, it does work well with a wired network connection (e.g. a USB hub with a network port) if you happen to have one lying around.

Before we install dasher, the Dash button needs to be configured following the Amazon instructions so that it stores the SSID and password of your home wireless network (but with the last step omitted - so that no product is associated with the button). Strangely, you need to use an Android or iOS mobile phone to do this - not a tablet. If, like me, you've only got a tablet, you can use a little-known Android app called Amazon Underground on an Android tablet. I forgot to say - if you order something with the button of your choice, you get the price of the button refunded, so it makes sense to get a button for something you use anyway, place one order then de-activate the button. Then go through the "add button" process again and quit the app before the final step.

How will we know if we have got our Dash button working? It makes sense to test it by controlling a GPIO pin first.

Let's get started

I started by following the instructions on the dasher git-hub page. However, my initial attempt didn't work; also, the version of node.js that you end up with is v4.0, although the current  (at the time of writing) version is 6.10.3. I thought I'd do it properly and install the latest version of node.js. First, I prepared my Raspberry Pi Zero W with a new image of Raspbian (date 10 April 2017). The current version of Raspbian comes with a very old version of  node, and this has to be updated for dasher to work properly. After configuring the timezone and WiFi interface, I installed a couple of pre-requisites (libpcap-dev and npm).
  • Open console and install node, libpcap-dev and npm
    #Install node.js to remove nodejs legacy 
    sudo apt-get install node
    sudo apt-get install libpcap-dev
    sudo apt-get install npm

    • Install newer version of Node.JS (I used ARM v6)
    wget https://nodejs.org/dist/v6.10.3/node-v6.10.3-linux-armv6l.tar.gz
    tar -xvf node-v6.10.3-linux-armv6l.tar.gz
    cd  node-v6.10.3-linux-armv6l
    sudo cp -R * /usr/local/
    sudo node --version


    This should respond with v6.10.3. If so, node is installed and up to date so we can proceed with installing dasher.
    • Install dasher
    cd ..
    sudo git clone https://github.com/maddox/dasher.git
    cd dasher
    sudo npm install

    N.B. ignore gyp warnings (doesn't seem to matter)
    Go and make a cup of coffee - installation takes a long time

    When that is finished, check that your button can be found (make a note of the MAC address if you haven't already done so)....
    sudo ./script/find_button

    Toggle a GPIO pin using dasher

    We can configure dasher to monitor the home network and run a shell script if it sees a "UDP" request from the MAC address of the Dash button to join the network (which it will do when the button is pressed). To do this, we need to modify the config.json file according to the example given in the dasher documentation. Mine looks like this:

    {"buttons":[
        {
           "name": "Command Exec Button",
           "address": "[MY MAC ADDRESS]",
           "cmd": "/home/pi/dash_button.sh"
        }
    ]}

    Now we need to write the shell script (dash_button.sh) to toggle a GPIO. I connected an LED (with resistor) to GPIO14 so that, when the Dash button is pressed, it toggles on/off.

    #!/bin/bash
    GPIO=14
    GPIODIR=/sys/class/gpio/gpio$GPIO

    # i.e. GPIODIR = /sys/class/gpio/gpio14
    # use $GPIODIR to save typing long folder trees
    echo "Configuring GPIO $GPIO"

    #check if gpio14 is already exported.
    # If not, export gpio14 then set as output
    if [ ! -e "$GPIODIR" ] #tests for the (not !) existence of gpio14 folder
    then
            echo "Exporting GPIO"
            echo $GPIO > /sys/class/gpio/export
    echo out > $GPIODIR/direction #set as output
    else
            echo "GPIO already exported"
    fi

    #now that gpio14 is configured, toggle on/off depending on state
    read state < $GPIODIR/value
    sleep 1
    echo $(( ! state )) > $GPIODIR/value


    Before you can run this shell script, you need to make it executable and add it to your path:
    sudo chmod -u+x dash_button.sh
    sudo cp dash_button.sh /usr/local/bin


    To run dasher:
    sudo npm run start

    IFTTT

    Now that we have got the button working with GPIO pins, we can use it to set up a trigger action using IFTTT instead (you can't do both with the same button, unfortunately). IFTTT allows you to connect web-enabled "services" together so that, IF something happens on one service (a "THIS" trigger), THEN an action will occur on another service (a "THAT" action).

    Assuming you have a Gmail account, a good one for testing purposes is to add a row to a Google Sheet each time the button is pressed.

    In this case, the "dasher" script will monitor the home network and trigger an HTTP request if it sees a "UDP" request from the MAC address of the Dash button to join the network (which it will do when the button is pressed).

    The next step is to configure the IFTTT "Maker Webhooks" service to "watch" for the HTTP request that the dasher script will generate when it sees the Dash button join the network. Assuming you have set up an account on IFTTT, you will need to activate the Maker Webhooks service which will generate your own private key (you will need this later).

    Now, in IFTTT you can build your applet. Click on the "+" in the applet builder and choose the Maker Webhooks service (Receive a web request) as the trigger. Give it a name (in my case "trigger_dash"). Now click on the "+" to add an action. Choose the "Google Drive" service, then "Add row to spreadsheet". You can leave all the defaults as they are and just press "Create action", then (on the next page that appears) "Finish". If you click on  the down arrow below your IFTTT user name on the main IFTTT page (top right) and choose Services, then choose the Maker Webhooks service you will be able to click on the Documentation button for that service (top right again) you will see the full URL that you need to generate (in dasher) in order to trigger the applet. This takes the format

    https://maker.ifttt.com/trigger/[EVENT NAME]/with/key/[YOUR KEY]

    Next make your own config.json file containing the mac address of your button and Maker Webhooks key. I recommend that you first rename or copy the config.json file you made to toggle a GPIO pin to config2.json or something else, so that you can always revert back to it if you need to test things are working.

    sudo nano /config/config.json

    Mine looks like this (note that "trigger_dash" is the name I used  in Maker Webhooks when setting up the IFTTT applet):
    {"buttons":[
       {
            "name": "trigger_dash",
            "protocol": "udp",
            "address": "[YOUR MAC ADDRESS]",
            "url": "https://maker.ifttt.com/trigger/trigger_dash/with/key/[YOUR KEY]",
            "method": "POST"
        }
    ]}


    I have kept it simple for testing purposes. Once you get it working you can add more buttons, or pass more information to IFTTT.
    sudo npm run start

    With any luck, you should see dasher start running and confirm that the button has been added. Now, we can configure it so that it runs automatically, every time that you start up the Raspberry Pi.

    Run from startup

    Just follow the instructions here. These instructions also show you how to check that your Dash button is being detected. Now, you should be able to reboot your Raspberry Pi then, every time the Dash button is pressed, Google will add a new line to a spreadsheet. If it doesn't work, open a console and type:
    tail -f /var/log/dasher.log

    That should show you if dasher detected the button press, and what it did. I have found that the IFTTT Google service doesn't always work. Good luck!

    Saturday 13 May 2017

    Transistor logic gates - where analogue becomes digital

    Introduction



    We all know that computers are made using thousands (or millions) of transistors, but not many of us have "hands on" experience of constructing the fundamental building-blocks of digital logic ourselves. Those building blocks are "logic gates".

    I decided to experiment with making my own logic gates using some of the many Snap Circuits components I have accumulated over the years.

    In electronics, a logic gate is a device implementing a Boolean function. Every possible logical function can be represented by a combination of only NAND gates or only NOR gates. In practice, other common logic gates such as AND, OR, NOT and XOR are also used as building blocks.

    Transistors


    Turning now to the transistor, if a sufficient voltage is applied between the collector and base (normally ~ 0.7V), this will allow current to flow between the collector and the emitter (i.e. it will "turn on" the transistor).


    A judicious choice of base resistor is necessary to prevent excessive current flowing through the base (destroying the transistor). Also, a "load" resistor should be chosen that allows sufficient but not excessive current to flow through the load device (i.e. output device). For my circuit, I used a 4.5V battery pack and NPN transistors (with base resistors of 1k Ohms) driving an LED through a 100 Ohm load (plus the 33 Ohm internal resistor). By applying sufficient (analogue) base voltage until current flows from the collector through the emitter, we have made a digital device (an electronic switch). This is the starting point for digital electronics.

    Logic gates

    The first, and simplest logic gate I built was the NOT gate (also known as an inverter). This needs just one transistor. If the input voltage is "high" (in logic terms "1"), then the output voltage is "low" (in logic terms "0") and vice versa.



    Next I built a NAND gate. This needs two transistors in series, with the output load being driven between the collector and ground (0V). nb. You can turn it into an AND gate by placing the load between the supply voltage and the collector. 



    The function of a NAND gate can be expressed in the truth table below (see All About Circuits):


    The final "building block" logic gate I built was a NOR gate which needs two transistors in parallel.



    The truth table is as follows:


    Now for something a bit more complicated - an Exclusive-OR ("XOR") gate. This outputs a “high” ("1") logic level if the inputs are at different logic levels, either 0 and 1 or 1 and 0. Conversely, it outputs a “low” ("0") logic level if the inputs are at the same logic levels.

    XOR gates can be constructed from various combinations of AND, OR, NAND, NOR or NOT gates. I made mine from pairs of NAND and NOT gates.

    Adders

    Finally, I made a "half adder" circuit by adding an AND gate in parallel with an XOR gate.


    Inspecting the truth table reveals that this circuit enables two one-bit binary numbers to be added together, giving a "sum" and a "carry".
    Finally, the full significance of all these logic gates can be appreciated. Using only transistors and resistors, a circuit can be created that adds two binary numbers together. Although there is a "carry" output, there is no "carry" input (hence the name half adder), so only one-bit numbers can be added together, which somewhat limits its usefulness.

    A full adder allows for "carry in" signals as well as "carry out" signals. This makes it possible to add larger numbers together, as there is a mechanism for carrying from a "less significant bit" to a "more significant bit". For example, by cascading eight full adders together, eight-bit binary numbers can be added together (i.e. numbers up to 255 in decimal).