If you haven’t heard about them, Amazon is putting out these shiny new buttons which are basically walking advertisements for certain brands of products. You can stick them to a wall with the included adhesive or hang them somewhere with the included ring (not pictured). What is even more interesting is that when you press one of these buttons they are supposed to place an order for a new product without any interaction on your part. They connect up to your home WIFI (with a bit of initial setup through the Amazon app) and beam the order request out to Amazon on the double so you can have your new garbage bags in a jiffy.

They come in veritable cornucopia of flavors right now, 18 buttons in all at the time of this writing. With multiple different companies vying for the opportunity to pitch their wares to you and get a little ad-space on your wall. Rumor has it that these companies are even paying Amazon for the privilege of being button-ized.

Amazon is pitching these things for $5 a piece right now to Amazon Prime members only. Although supposedly you’ll get a $5 discount when you place your first order of product X using the button. You’ve really got to hand it to Amazon here, they’re making money on both ends, from the business AND the user. Let’s forget the fact that the whole concept is just a bit ridiculous (even for a technophile like me)… that they’d expect you to pay $5 for the convenience of hitting a button to order a product. That you would be so lazy as to not even perform the most rudimentary of price comparisons. That you would be willing to pay the iron price Amazon price for whatever good… whatever it happens to be. Are we all really that lazy busy?

Poor product ideas aside, I immediately plopped down $10 in Amazon gift card money and bought two of them right before my Prime subscription ran up because something tells me these aren’t going to be on the market for very long. After being inspired by Ted Benson I had a feeling there must be something I could set these up for.

I purchased the most basic dash button model I could find with the least offensive advertisements… in this case this was the Amazon Elements model. When they arrived I immediately covered up the amazon logos with a label maker and called the buttons, very memorably, #1 and #2.

Setup of the buttons is really simple but you must be careful to NOT COMPLETE THE SETUP. You wouldn’t want these buttons to actually order something hahaha. If you accidentally do complete the setup (like I did), you can dissociate the button from whatever product you picked but I recall it being an extra annoying step. Read the Ted Benson article here for clues on where to abort the setup process. For me it was as simple as force-closing the app on my phone when it prompted me to select the radio-button for a corresponding product. Presto chango the button was now rendered useless. It will still connect to your home Wifi and communicate to Amazon but it will not complete the ordering process.

Actually if you were to stop right here things would be quite annoying for you because every time you hit the button it still communicates with Amazon and then the silly phone app blows-off an annoying message to you reminding you to finish setting up your button. This gets old really quickly even when I was testing– even more fun is that the notifications stack up in Android so you’d have a list a mile long of notifications unless you take the next steps.

1). Setup a static IP for the button

2). Block all traffic from that IP out to the internet

You can use “discover mode” shown in python code below to learn which MAC address your dash button has in order to properly bind it to a static IP. Regarding the ability to block traffic, not every home Wifi router can support this function but if you have a newer router like the super-awesome Asus RT-AC68U you’re good to go. In my case I built a rule that applied to all hours of every day and applied that to the IP addresses of the two buttons for all of both kinds of traffic, TCP and UDP. Basically these things are now entirely disconnected from the internet.

Sure enough, when I applied these rules and continued pressing these buttons, I no longer received any notifications from Amazon. One side effect of this action is that the buttons stay awake longer as they try (and fail) to communicate with Amazon; I would estimate about 30 seconds in total although I have not specifically timed it.

Onto the fun stuff.

Now that the buttons are setup I cannibalized and re-factored some code to listen for them on the network. Here is what I ended up with.

#!/usr/bin/python import sys import time import socket import struct import logging import binascii import subprocess logging.basicConfig(filename='/var/log/dashbutton.log', level=logging.INFO, format='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S -- ') discover_mode=False if len(sys.argv) > 1: if sys.argv[1] == "discover": discover_mode=True rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003)) buttons={ "00bb3aff6aea_192.168.1.00":["Button One",0,["/home/pi/scripts/WEMO/send_wemo_commands.py","sendall.toggle"]], "747548bd4908_192.168.1.255":["Button Two",0,["/home/pi/scripts/WEMO/send_wemo_commands.py","kitchensink.toggle"]]} logging.info(' ### Dash Button Service Started ### ') while True: packet = rawSocket.recvfrom(2048) ethernet_header = packet[0][0:14] ethernet_detailed = struct.unpack('!6s6s2s', ethernet_header) arp_header = packet[0][14:42] arp_detailed = struct.unpack('2s2s1s1s2s6s4s6s4s', arp_header) # skip non-ARP packets ethertype = ethernet_detailed[2] if ethertype != '\x08\x06': continue source_mac = binascii.hexlify(arp_detailed[5]) dest_ip = socket.inet_ntoa(arp_detailed[8]) identifier=source_mac+"_"+str(dest_ip) if discover_mode: logging.info("We saw an arp from MAC: " + str(source_mac) + " ip: " + str(dest_ip)+ "

") continue if identifier in buttons: buttons[identifier][1] += 1 #iterate the count of button presses logging.info(buttons[identifier][0] + " Pressed " + str(buttons[identifier][1]) + " times.

") subprocess.Popen(buttons[identifier][2],stdout=subprocess.PIPE).communicate()[0]

Or download the code from my Github Gist page.

The code has two modes in which it can be run:

Discover mode: ./dash_button.py discover

Vanilla mode: ./dash_button.py

In discover mode the script will call out whatever MAC addresses it sees sourcing ARP packets… Press your button here and see what addresses your button owns. Once you’ve defined the static IPs in your router come back to the script and update the buttons dictionary with your “tuple” of MAC and IP address followed by your colloquial name for the button, the number of times it’s been pressed and lastly the command that should be executed by subprocess when the button is pressed.

Now you can run the script in vanilla mode to test pressing your button.

A simple few lines of code which sniff all incoming traffic listening for ARPs from a specific tuple of source MAC and IP address. Since this script is essentially sniffing all incoming packets you’ll want to situate this code on a remote part of your network that doesn’t process big file transfers or the like. In my case I have this code sitting on a Raspberry Pi that isn’t used for much.

Reading the code, you can see the “tuple” as the key for the “buttons” dictionary this is the key to identifying traffic we care about. The format for the buttons dictionary is rudimentary but functional and avoids making a class for something really simple.

In my example I’m kicking off WEMO Events whenever buttons are pressed. I keep button #2 by my nightstand and press it to turn off my kitchen light when I go to bed. Button #1 just toggles every light switch in the house for fun.

Starting the Script on Boot:

I built an Upstart job to start the script at each boot. In order to use this method, you’ll need to install Upstart on your Pi with:

pi@pi ~ $ sudo apt-get install upstart Reading package lists... Done Building dependency tree Reading state information... Done Suggested packages: graphviz The following packages will be REMOVED: sysvinit The following NEW packages will be installed: upstart WARNING: The following essential packages will be removed. This should NOT be done unless you know exactly what you are doing! sysvinit 0 upgraded, 1 newly installed, 1 to remove and 81 not upgraded. Need to get 502 kB of archives. After this operation, 940 kB of additional disk space will be used. You are about to do something potentially harmful. To continue type in the phrase 'Yes, do as I say!' ?] Yes, do as I say! Get:1 http://mirrordirector.raspbian.org/raspbian/ wheezy/main upstart armhf 1.6.1-1 [502 kB]

You can see during the Upstart install the system actually prompts you for such a big change with some special language [bolded above].

After Upstart is installed give your Pi a reboot:

sudo reboot

Lastly build the Upstart job by creating a file called “/etc/init/dashbutton.conf” and adding the following contents [replacing the exec line with the location where you have stored the script on your machine]:

author "Eric Pulvino -- AlwaysTinkering.wordpress.com" description "Upstart Script to run Amazon Dash Button service" start on runlevel [2345] stop on runlevel [016] respawn exec /home/pi/scripts/dash_button.py

That’s it. You can reboot your Pi to automatically start the service now however you could also just run the following command to start the service manually:

sudo service dashbutton start

Summary:

I’m sure there will be more in store for the buttons down the road with Halloween so close by. My typical Halloween goal is to literally scare the neighborhood children (and adults to death) so I might setup the use of the buttons to disable some of the really scary effects for 30-60 seconds when I see little children coming up the walk. Either way I’ll be sure to post some of my Halloween antics this year!