#!/usr/bin/env perl use strict; use warnings; use diagnostics; use feature qw(:all); use WWW::Curl::Easy; use Net::MQTT::Simple; use JSON::Parse qw(:all); use Amazon::Dash::Button; my ($response_body, $info, $postfields, $space_status, $new_space_status); my ($status, $site, $user, $pass, $mac, $curl, $json, $dev, $timeout); my ($mqtt, $topic, $message, $mqttuser, $mqttpass, $mqttIP, $mqttonly); $status = "https://spaceapi.c3l.lu/status.json"; # SpaceAPI direct link to status json file $site = "https://spaceapi.c3l.lu/open"; # SpaceAPI direct link to change the state $user = ""; # SpaceAPI user $pass = ""; # SpaceAPI pass $mqttIP = "127.0.0.1"; # MQTT Server IP $mqttuser = ""; # MQTT User $mqttpass = ""; # MQTT Pass $mqttonly = "True"; # MQTT Only modus active = not changing Space Status by myself $mac = 'de:ad:be:ef:0a:0a'; # MAC of Dash button. $timeout = 60; # Timeout in seconds. $ENV{'MQTT_SIMPLE_ALLOW_INSECURE_LOGIN'} = 1; # Needed for the MQTT Login $mqtt = Net::MQTT::Simple->new($mqttIP); $mqtt->last_will("availability/dashbutton", "offline", 1); # YOu may need to change the Topic $mqtt->login($mqttuser, $mqttpass); $mqtt->retain("availability/dashbutton", "online"); say "[+] Connection to MQTT server established"; say "[+] Scanning network traffic"; Amazon::Dash::Button->new( from => { # The author of the module says that you mac => $mac, # can omit a "dev" option to use another onClick => \&spaceapi, # network interface but actually it never name => q{SpaceAPI}, # gets used in the code. See the provided timeout => $timeout # patch to define a different interface. } )->listen; # Patch changes default to eth0. sub spaceapi { say "[+] Button has been pushed"; $mqtt->publish("space/status/trigger" => 1); say "[+] MQTT message sent"; if ($mqttonly eq "False") { $curl = WWW::Curl::Easy->new; $curl->setopt(CURLOPT_URL, $status); $curl->setopt(CURLOPT_VERBOSE,0); $curl->setopt(CURLOPT_WRITEDATA,\$response_body); $curl->perform; $info = $curl->getinfo(CURLINFO_RESPONSE_CODE); say "[-] Server returned $info" and exit unless $info == 200; $json = valid_json($response_body); say "[-] Malformed json!" and exit unless $json; $json = parse_json($response_body); if ($json->{state}{open} and $json->{state}{message} =~ /members only/i) { $space_status = 2; # Propably needed in the future $new_space_status = "CLOSED"; $postfields = "close=close&message="; } elsif ($json->{state}{open}) { $space_status = 1; # Propably needed in the future $new_space_status = "CLOSED"; $postfields = "close=close&message="; } else { $space_status = 0; # Propably needed in the future $new_space_status = "OPEN"; $postfields = "open=open&message="; } $curl->setopt(CURLOPT_URL, $site); $curl->setopt(CURLOPT_VERBOSE,0); $curl->setopt(CURLOPT_USERPWD,"$user:$pass"); $curl->setopt(CURLOPT_COOKIEFILE, 'cookiescurl'); # Apparently you need this $curl->setopt(CURLOPT_COOKIEJAR, '/tmp/cookiescurl'); # to make Digest Auth work $curl->setopt(CURLOPT_HTTPAUTH,CURLAUTH_DIGEST); # ...sad! $curl->setopt(CURLOPT_POSTFIELDS(), $postfields); $curl->perform; $info = $curl->getinfo(CURLINFO_RESPONSE_CODE); say "[-] Server returned $info" and exit unless $info == 302||200; say "[+] Changed Space Status to $new_space_status"; } } =README SpaceAPI Amazon-Dash-Button-Trigger +-------------------------INSTALL-------------------------+ | | | 1) Patch Amazon::Dash::Button with the diffs provided | | 2) ??? | | 3) Profit! | | | +---------------------------------------------------------+ =MAC ADDRESS Find out the mac address of your dash button by running: perl -MAmazon::Dash::Button -e 'Amazon::Dash::Button->search(dev => q{eth0}, cache => 1)' If this does not show an entry with "Amazon" behind it then you have a Dash button of the newer generation. This is not a problem as it now acts as 0.0.0.0:68. Take the shown MAC of this entry as it's actually your dash button. =RUN Needs to be run as root as it's using PCAP to check whenever the button has been pushed. =cut