Last Saturday, I took a 4 hour nap. I thought it was a fantastic use of my time, until I walked downstairs and saw that my roomate, the amateur carpenter that he is, had started and (for the most part) finished building a bar. Then I felt like I was wasting my life away, so I decided I should get around to doing a side project of my own.
Since my side project queue is a bit backed up, I decided to program a dash button to control the Phillips Hue lights in my room. A project that I decided I was going to do way back when I saw the original Amazon Dash Button hack article on Hacker News back in 2015. Based on said article, I thought the project would be a quick copy/paste job, unfortunately, dash buttons have changed a little bit over the years, so I thought I would clue anyone else who is just getting to 2015 trends in on the changes.
Nothing much about getting started has changed.
Get a RaspberryPi
Get an Amazon Dash Button
- Pro-Tip: The dash button brands that don’t sell well Amazon puts on sale for $.99
Go through the setup for the dash button, until it tells you to pick which product to purchase on press. As soon as you get there, quit the app.
Now, you’re button should be communicating with your wireless network when it’s pressed, it’s time to have your RaspberryPi run a python script to detect that communication.
Detecing the button’s MAC address
While sniffing your network, we’re going to run across all kinds of packets from your laptop, phone, Roku, Xbox… literally everything connected to your network, so we need to determine your dash button’s MAC address in order to be able to tell if any given packet is from the button or one of the many other internet connected devices that tend to accumulate in a home.
Now the original article will call for you to run this scanning code to get the MAC address:
from scapy.all import * def arp_display(pkt): if pkt[ARP].op == 1: #who-has (request) if pkt[ARP].psrc == '0.0.0.0': # ARP Probe print "ARP Probe from: " + pkt[ARP].hwsrc print sniff(prn=arp_display, filter="arp", store=0, count=10)
But times seem to have changed.
To detect the MAC address now run:
from scapy.all import * def arp_display(pkt): if pkt[ARP].op == 1: #who-has (request) print "ARP Probe from: " + pkt[ARP].hwsrc print sniff(prn=arp_display, filter="arp", store=0, count=10)
But don’t forget to install the Scapy library first.
apt-get install scapy
And unless you want to occasionally get a weird error when running it, install the libraries that Scapy suggests.
apt-get install tcpdump tcpreplay wireshark
If you get this error:
socket.error: [Errno 1] Operation not permitted
run as sudo.
Oh, and you’re going to have to actually push the button (while the scanning script is running), since it will only communicate with the router on press.
ARP Probe from: MACADDESS
And, now we have the MAC address.
Detect dash button press
To detect the dash button press, the original article calls for a simple modification to the scanning script:
def arp_display(pkt): if pkt[ARP].op == 1: #who-has (request) if pkt[ARP].psrc == '0.0.0.0': # ARP Probe if pkt[ARP].hwsrc == 'MACADDRESS': # code to call on dash button press print sniff(prn=arp_display, filter="arp", store=0, count=10)
I found that that code was detecting 2 different packets from my dash button per press, so I had to modify the script to only be triggered on every other packet:
counter = True def arp_display(pkt): global counter if pkt[ARP].op == 1: #who-has (request) if pkt[ARP].hwsrc == '50:f5:da:f8:d9:5e': if(counter): counter = False # code to call on dash button press else: counter = True sniff(prn=arp_display, filter="arp", store=0, count=0)
Pretty straight forward, as long as you haven’t taken ~4 years off from Python and remember:
To add the global keyword in the arp_display function
That booleans are capitalized in Python
To get the program to run without terminating, we have to change the final line from:
print sniff(prn=arp_display, filter="arp", store=0, count=10)
print sniff(prn=arp_display, filter="arp", store=0, count=0)
And unless you’re planning on constantly monitoring it, let’s go ahead and remove the print call:
sniff(prn=arp_display, filter="arp", store=0, count=0)
Finally, don’t forget to start your program by modifying /etc/rc.local on your pi.
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi python /path/to/your/fileName.py & exit 0
Oh, and the Amazon app will send you a push notification everytime you press the button reminding you to “Finish the Setup process to use your dash button”. I just turned off push notifications from the app, and turned on text notifications for my orders.
My dash button turning off my overhead light, and turning on my lamp.