From 182e250bc953b3eac8373c0abf585a16192fc9e2 Mon Sep 17 00:00:00 2001 From: Adam Dodman Date: Thu, 24 Nov 2016 00:20:01 +0000 Subject: [PATCH] Initial Commit --- .gitignore | 1 + Dockerfile | 12 +++++++++ Readme.md | 32 ++++++++++++++++++++++++ main.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 Readme.md create mode 100644 main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c00dcf4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +dash.cfg diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..325f410 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM alpine:3.4 +MAINTAINER "Adam Dodman " + +RUN apk add --no-cache python py-pip \ + && pip install --upgrade pip \ + && pip install paho-mqtt scapy \ + && mkdir dash \ + && ln -s /config/dash.cfg /dash/dash.cfg + +ADD main.py /config + +CMD ["python","/dash/main.py"] diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..25034c1 --- /dev/null +++ b/Readme.md @@ -0,0 +1,32 @@ +# Amazon Dash Button to MQTT Bridge + +Sends an MQTT message when an Amazon Dash button press is detected. + +Dash detection code based on [sejnub/docker-amazon-dash-sniff](https://github.com/sejnub/docker-amazon-dash-sniff) + +## Dash Button Setup +3. Go through the normal Dash button setup in the Amazon app, but when asked to select a product, simply exit out of the setup process. + +4. Find the mac address of the Amazon button. This can usually be achieved through your router. If in doubt, use a [MAC address vendor checker](https://macvendors.com/) to make sure the MAC is reigstered to "Amazon Technologies inc." + +5. (Optional) Block the button from accessing the internet. Different routers have different ways of achieving this, but typically a simple IPTables rule will achieve this. + +## Usage +1. Install Python (>= 2.7), as well as scapy, configparser and paho-mqtt from pip. + +2. Clone this repo + +3. Run main.py to generate the example config. + +4. Edit the config provided to include your MQTT host, as well as the MAC addresses of the button and the corresponding MQTT channels to message. (See the config for examples.) + +5. Run main.py + +** OR ** +1. Run the docker image: +``` docker run -d --net=host --name="mqtt-dash" -v $YOUR_CONFIG_DIRECTORY:/config adamant/mqtt-amazon-dash``` + +2. Edit the config provdided by the program. + +3. Start the container again: +``` docker start mqtt-dash ``` diff --git a/main.py b/main.py new file mode 100644 index 0000000..68c4dc1 --- /dev/null +++ b/main.py @@ -0,0 +1,72 @@ +from backports import configparser +import os +import paho.mqtt.client as mqtt +import logging +from time import sleep + +logging.getLogger("scapy.runtime").setLevel(logging.ERROR) +from scapy.all import * + +mqttc = mqtt.Client() + +defaultconfig = '''[MQTT] +# The hostname or IP of the MQTT Server +host = +# The Port of the MQTT Server (Default: 1883) +#port = +# Is a Username and Password required? (Default: false) +#auth = True +# Username (If required) +#user = +# Password (if required) +#pass = + +[Buttons] +# For every line, list the MAC of the button, and the MQTT topic to publish to. +01:23:45:67:89:ab = example/example_topic''' + +def arp_display(pkt): + topic = '' + foundmac = None + if pkt.haslayer(ARP): + if pkt[ARP].op == 1: #who-has (request) + i = 0 + for j in macs: + if (macs[i] == pkt[ARP].hwsrc): + foundmac = i + i += 1 + if not (foundmac == None): # If we have actually found a matching mac + print 'Found ARP for MAC %s, sending to topic %s' % (macs[foundmac], topics[foundmac]) + mqttc.publish(topics[foundmac], "ON") # Both to simulate button press + mqttc.publish(topics[foundmac], "OFF") + + +if __name__ == '__main__': + if not (os.path.isfile('./dash.cfg')): + print('Warn: Config file does not exist, writing example config. Please configure and try again.') + c = open('./dash.cfg', 'w') + c.write(defaultconfig) + c.close() + exit(1) + + config = configparser.ConfigParser(delimiters=('=')) + config.read('./dash.cfg') + hostname = config['MQTT'].get('host') + port = config['MQTT'].get('port') + authrequired = config['MQTT'].getboolean('auth', False) + if (authrequired): + username = config['MQTT'].get('user') + password = config['MQTT'].get('pass') + + macs = [] + topics = [] + for option, value in config.items('Buttons'): + macs.append(option) + topics.append(value) + print 'Importing mac %s with topic %s' % (option,value) + + if (authrequired): + mqttc.username_pw_set(username,password=password) + mqttc.connect(hostname) + mqttc.loop_start() + sniff(prn=arp_display, filter="arp", store=0, count=0)