I recently acquired a few Amazon Dash buttons and wondered if they might be repurposed to serve some useful purpose, other than ordering groceries.
I found this article by Ted Benson in which he describes how Dash buttons send an ARP probe after joining the WiFi network. By listening for these ARP probes (and their unique MAC addresses) you can trigger IFTTT Webhooks workflows, which turns the humble Amazon ordering tool into a customisable IoT button.
Bob Steinbeiser replied to Ted’s post with a clever Python script which sniffs ARP packets using a raw socket. Having played with Bob’s script I set about trying to make a few improvements. I’m a novice when it comes to Python though, so forgive my amateur code.
import socket import struct import binascii import urllib2 import time # Based on an original script by Bob Steinbeiser (https://medium.com/@xtalker) # Adapted to ignore duplicate presses and added support for multiple IFTTT triggers # Use your own IFTTT Webhooks key here - see https://ifttt.com/maker_webhooks ifttt_key = 'abc123' # MAC addresses and their corresponding IFTTT Webhooks triggers things = { 'aabbccddeeff' : ['lights_off', 'sockets_off'], 'a0b1c2d3e4f5' : ['test_1', 'test_2', 'test_3'] } last_success={} for macaddr in things: last_success[macaddr] = 0 rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003)) 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]) time_now = int(time.time()) # Is this a known 'thing' ? if source_mac in things: trigger_list = things[source_mac] # Prevent duplicate presses from being actioned (within 10 secs) if time_now > last_success[source_mac] + 10: # Supports multiple IFTTT Webhook triggers for trigger in trigger_list: print "Device " + source_mac + " has triggered " + trigger last_success[source_mac] = int(time.time()) data = '{ "value1" : "' + source_mac + '", "value2" : "' + trigger + '" }' req = urllib2.Request('https://maker.ifttt.com/trigger/' + trigger + '/with/key/' + ifttt_key, data, {'Content-Type': 'application/json'}) f = urllib2.urlopen(req) response = f.read() f.close() print response else: print "Ignoring repeated event for " + source_mac else: print "Ignoring unknown device " + source_mac
Note that this Python script doesn’t work on Mac OS, due to the lack of support for AF_PACKET sockets.