Tracking our pug's feedings with an amazon dash hack

Summary

In the original post on Medium[1], Ted Benson had a great idea to listen for the Amazon Dash button presses on his network to trigger a more... useful action.

After I told my wife about this fun hack we started brainstorming and decided that our inability to communicate when we feed our slightly obese pug would be a great excuse to hack this button. For those bored at home, you can follow Chuy's amazing journey.

WinPCAP & SharpPCAP

WinPcap is the packet capture library for windows. We'll use the WinPcap library to listen for ARP packets on our wired or wifi network via the SharpPcap .NET library. If you don't already have WinPcap installed follow the link below.

https://www.winpcap.org/install/

Devices

WinPcap calls network interfaces devices. The first thing our app does is get a list of all available packet capturing and sending devices on your local computer. My DashSniffer app will look at the app.config for a device name and determine if it is legitimate or requires the user to select a new device.

<add key="DeviceName" value="\Device\NPF_{25EAE124-F896-4BBE-9CEA-091D560035C0}"/>

Packet capture events

SharpPcap has an easy event handler we can attach a custom method to which will filter activity to only ARP request packets.

device.OnPacketArrival += DashEventHandler.Resolve;
if (packet?.Type == EthernetPacketType.Arp)
    PostDashEvent(packet);

You can install SharpPcap from nuget via:

Install-Package SharpPcap

MAC address filtering & service call

Because Amazon is so concerned with extending the life/usage of the Dash a wifi connection is only made when the button is pushed. This is what triggers the Dash to perform an ARP request asking our network for an IP address followed by an ARP acknowledgement after it has successfully joined.

To get around picking up both ARP packets and falsey assuming the button was pushed twice we'll filter on the dash's initial IP of 0.0.0.0.

if (((ARPPacket)packet.PayloadPacket).SenderProtocolAddress.ToString() != "0.0.0.0")

The second filter determines if the MAC address of the packet captured has a configuration setup for it.

I've setup my app.config app settings section to contain an entry for each button, though you can get as fancy as you'd like with it; I'll never have more than a handful so I'll just YAGNI that. I chose to go with a pattern that will help me associate MAC addresses with the physical device e.g. Dash.<Product>.<MACAddress> as the app setting key and then an event name such as "FedChuy" for the value.

<add key="Dash.Wellness.B703UC128843" value="FedChuy" />

To obtain the key/value I run a contains on all app settings.

var button = ConfigurationManager.app settings.AllKeys.SingleOrDefault(m => m.Contains(macAddress));

After the button index has been found I'll use it to obtain the value from the setting and pass it onto my web service though a [System.Net.Http.HttpClient] POST.

Amazon Dash MAC address

One thing I didn't build into the app was auto detection of a dash device. To obtain each MAC address I used Wireshark[4] and watched for ARP requests to popup. Easy enough the requests typically come across as "Amazon<Something>".

Notice the double ARP request I mentioned earlier? Click on the details of one the requests and we can see device's MAC address.

With this information I can now fill out my app settings so my program knows what to listen for.

<add key="Dash.Huggies.A002DC116271" value="UsedTheFacilities" />

Now when a Dash button is pressed the DashSniffer app will see the ARP request with a MAC address of A002DC116271 and fire off a POST to my Web API endpoint with a value of "UsedTheFacilities". From that point on it is up to us what to do with that data.

Conclusion

The program has been running now flawlessly for a little over a week and we're surprisingly using the tracking page daily for its intended use. Next step is to mount my wife's Kindle Fire in our kitchen to keep Chuy's page up and easily visible 24/7. In the meantime keep thinking up neat hacks so I can put aside my real work.