Experiences on the Front Lines of User Interfaces and Web Development

Hacking the Amazon Dash Button - Mac OS X Yosemite tutorial

So there has been a lot of buzz lately regarding hacking the Dash button. My friend and coworker, who is a real American hero, wrote a post just yesterday summarizing his genius pizza-dash button integration. Of course original credit still goes to Ted Benson.

While hearing about Brody's adventures, I was curious to try it myself, so when my dash button arrived I too played around with turning it into something handy.

I ran into several gotchas while attempting to follow Ted's post that I wanted to capture here in case it helps any other fellow hackers!

Getting it all working

Note: I am on Mac OS X Yosemite, and I already had XCode 7 and command line tools installed.

Installing Scapy wasn't bad (I did brew install wget first so I could easily follow their instructions):

$ wget scapy.net
$ unzip scapy-latest.zip
$ cd scapy-2.*
$ sudo python setup.py install

Missing Dependencies

The problem was, even with Scapy installed, the python script from Ted to capture Arp packets did not run due to missing dependencies. I got an error saying the pcap module wasn't found, then after fixed an error about dnet. This blog post helped me out:

Install PCAP python module:

$ wget http://downloads.sourceforge.net/project/pylibpcap/pylibpcap/0.6.4/pylibpcap-0.6.4.tar.gz
$ tar xfz pylibpcap-0.6.4.tar.gz
$ cd pylibpcap-0.6.4
$ sudo python setup.py install

Install dnet python module:

$ wget https://github.com/dugsong/libdnet/archive/libdnet-1.12.zip
$ tar xfz libdnet-1.12.tgz
$ cd libdnet-1.12
$ ./configure
$ make
$ sudo make install
$ cd python
$ sudo python setup.py install

Python server kept stopping

Another big gotcha was the example python script that listens for ARP requests has this line:

print sniff(prn=arp_display, filter="arp", store=0, count=10)  

The count=10 at the end means after it sniffs out 10 arp packets it will exit, printing [] to the screen! That was definitely confusing for me, as I expected this script to listen in an infinite loop for requests, so when I was testing it out with my dash button, half the time I would fine the program had already shut down. Simply remove that last argument in the sniff command.

Putting it all together

Once you get the arp packet hook working for your specific Dash's MAC address, you can kick off any task or home automation event (that you are able to script from your laptop, of course).

I played around with play/pause of Sonos, since I often find myself in a room with our Sonos but without my phone (or I don't want to unlock phone, find the app, and click play).

Here was my simple script:

# dash-listen.py
from scapy.all import *  
import requests  
import time

ZIPLOC_MAC_ADDR = '...'

def play_pause_sonos():  
  print("Triggering Play Sonos script")
  os.system("osascript play-sonos.scpt") 

def arp_display(pkt):  
  print "incoming packet"

  if pkt[ARP].op == 1 or pkt[ARP].op == 2: #who-has or is-at (request)
    if pkt[ARP].psrc == '0.0.0.0': # ARP Probe

      if pkt[ARP].hwsrc == ZIPLOC_MAC_ADDR:
        play_pause_sonos()

      else:
        print "ARP Probe from unknown device: " + pkt[ARP].hwsrc

print sniff(prn=arp_display, filter="arp", store=0)  
-- play-sonos.scpt
tell application "System Events"  
  tell process "Sonos"
    set frontmost to true
    keystroke "p" using command down
  end tell
end tell  
comments powered by Disqus