[PYTHON] "Amazon Dash Button" ist in Japan gelandet, aber ich habe es gewagt, es selbst zu machen

DashButtonCover.jpg

Überblick

Neulich wurde "Amazon Dash Button" endlich in Japan veröffentlicht. Der Punkt ist, dass wenn Sie auf die Schaltfläche klicken, das Zielprodukt automatisch von Amazon bestellt und zu Ihnen nach Hause geliefert wird. Machen wir das diesmal selbst! Es ist ein Artikel in diesem Sinne.

Diejenigen, die es verstehen, werden verstehen, aber um genau zu sein, diejenigen, die "AWS IoT Button" sagen, eine programmierbare Version von "Amazon Dash Button". Ich denke es ist nah.

Gesamtstruktur

Die Gesamtarchitektur ist wie folgt:

全体構成.png

  1. Drücken Sie die an Raspberry Pi Zero angebrachte Taste, um über MQTT eine Verbindung zu AWS IoT herzustellen.
  2. Die AWS IoT Rules Engine leitet Nachrichten an AWS Lambda weiter.
  3. Die Lambda-Funktion durchsucht die Amazon-Website von Selenium + PhantomJS und kauft das angegebene Produkt.

Ich werde dies im Hintergrund des Prozesses ausführlich erläutern (in der Reihenfolge 3-> 2-> 1).

1. Erstellen Sie eine Lambda-Funktion für den automatischen Kauf bei Amazon

In diesem Kapitel werden wir Selenium und PhantomJS verwenden, um die Amazon-Website zu crawlen und eine Lambda-Funktion zu erstellen, die den angegebenen Artikel automatisch kauft.

Was ist AWS Lambda?

http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/welcome.html Wenn AWS Lambda Code in AWS Lambda hochlädt, wird der Service zu einem Computerdienst, der die AWS-Infrastruktur verwendet, um die Ausführung des Codes zu übernehmen.

Java, Node.js, Python, C # können für die Laufzeit ausgewählt werden, aber dieses Mal werden wir Python verwenden.

Paketkonfiguration

Platzieren Sie den Lambda-Funktionskörper und die erforderlichen Bibliotheken direkt unter dem Projektverzeichnis.

$ tree -L 1
.
├── amzorderer.py				#Lambda-Funktionskörper
├── phantomjs					#PhantomJS binär
├── selenium					#Selenium-Bibliothek für Python
└── selenium-3.0.2.dist-info

Referenz: https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html

Selen-Installation

Installieren Sie Selenium mit pip direkt unter dem Projektverzeichnis.

pip install selenium -t /path/to/project-dir

PhantomJS-Installation

Laden Sie die Linux 64-Bit-Version von tar von PhantomJS Official herunter und platzieren Sie phantomjs im bin-Verzeichnis direkt unter dem Projektverzeichnis.

Erstellen einer Lambda-Funktion

Der Quellcode ist auch unten verfügbar. (Geplant, später veröffentlicht zu werden)

amzorderer.py


# -*- coding:utf-8 -*-

__author__ = 'H.Takeda'
__version__ = '1.0.0'

import os
import boto3

from argparse import ArgumentParser
from base64 import b64decode
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

# Amazon top page url.
AMAZON_URL = "https://www.amazon.co.jp"
# Amazon user id (email).
AMAZON_USER = boto3.client('kms').decrypt(
    CiphertextBlob=b64decode(os.environ['user']))['Plaintext']
# Amazon user password.
AMAZON_PASS = boto3.client('kms').decrypt(
    CiphertextBlob=b64decode(os.environ['password']))['Plaintext']
# User agent.
USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/53 (KHTML, like Gecko) Chrome/15.0.87"
# Item dictionary.
ITEMS = {
    "01": "1fLhF7q",    # Toilet Paper
    "02": "fhYcbp7"     # Saran Wrap
}


def lambda_handler(event, context):
    # Create web driver for PhantomJS.
    dcap = dict(DesiredCapabilities.PHANTOMJS)
    dcap["phantomjs.page.settings.userAgent"] = USER_AGENT
    driver = webdriver.PhantomJS(desired_capabilities=dcap,
                                 service_log_path=os.path.devnull,
                                 executable_path="/var/task/phantomjs")

    # Get amazon top page.
    driver.get(AMAZON_URL)
    # Transition to sign in page.
    driver.find_element_by_id("nav-link-yourAccount").click()
    # Input user id.
    driver.find_element_by_id("ap_email").send_keys(AMAZON_USER)
    # Input user password.
    driver.find_element_by_id("ap_password").send_keys(AMAZON_PASS)
    # Sign in.
    driver.find_element_by_id("signInSubmit").click()
    # Select item.
    driver.get("http://amzn.asia/" + ITEMS[event["item"]])
    # Add to cart.
    driver.find_element_by_id("add-to-cart-button").click()
    # Proceed to checkout.
    driver.find_element_by_id("hlb-ptc-btn-native").click()
    # Order.
    # driver.find_element_by_name("placeYourOrder1")[0].click()
    driver.save_screenshot("hoge.png ")
    driver.quit()

Grundsätzlich mache ich nur eine einfache Selen-Operation, aber ich werde die Punkte aufgreifen.

Bereitstellen von Lambda-Funktionen

Archiv

Zippen Sie das Projektverzeichnis. Der Name der Zip-Datei spielt keine Rolle.

$ zip -r upload.zip /path/to/project-dir/*

Lambda-Funktionseinstellungen

Stellen Sie die Lambda-Funktion über die AWS-Verwaltungskonsole ein. Sie können die erstellte Zip-Datei auch hier hochladen.

Lambda Management Console.png

Lambda-Funktionstest

Stellen Sie das Testereignis (Parameter, der an die Lambda-Funktion übergeben wurde) unter Aktionen> Testereignis konfigurieren ein. Drücken Sie die Test-Taste, um die Lambda-Funktion auszuführen.

Lambda Management Console2.png

Es ist in Ordnung, wenn der Vorgang normal abgeschlossen ist. Damit ist die Erstellung der Lambda-Funktion abgeschlossen, die automatisch bei Amazon gekauft wird.

2. AWS IoT-Einstellungen

In diesem Kapitel verwenden wir AWS IoT, um MQTT-Anforderungen zu akzeptieren und die Einstellungen zum Aufrufen der oben erstellten Lambda-Funktion zu konfigurieren.

Was ist AWS IoT?

https://aws.amazon.com/jp/iot/how-it-works/ Durch die Verwendung von AWS IoT ist es möglich, verschiedene Geräte mit verschiedenen AWS-Diensten zu verbinden, Daten und Kommunikation zu schützen sowie Verarbeitung und Aktionen für Gerätedaten durchzuführen.

Geräteregistrierung

Registrieren Sie das Gerät, das eine Verbindung zu AWS IoT herstellt, über den Bildschirm der AWS IoT-Konsole.

  1. Fahren Sie mit dem Registrierungsbildschirm von "Erste Schritte" fort.

AWS IoT0.png   2. Wählen Sie die Umgebungsinformationen für das Clientgerät aus. Dieses Mal stellen wir über das Python SDK eine Verbindung zu AWS IoT von Raspberry Pi Zero (OS: Raspbian) her.

AWS IoT4.png   3. Geben Sie einen beliebigen Gerätenamen ein (in diesem Fall raspi0) und klicken Sie auf "Nächster Schritt".

AWS IoT5.png   4. Drücken Sie "Liux / OSX", um den öffentlichen Schlüssel, den privaten Schlüssel und das Client-Zertifikat herunterzuladen (Sie werden sie später verwenden). Klicken Sie auf "Nächster Schritt", um zum nächsten Bildschirm zu gelangen.

AWS IoT7.png   5. Die Geräteeinstellung wird angezeigt. Drücken Sie zum Abschluss "Fertig".

Regelregistrierung

Legen Sie fest, dass die Lambda-Funktion aufgerufen wird, wenn eine Nachricht zu einem bestimmten Thema veröffentlicht wird.

  1. Fahren Sie mit dem Registrierungsbildschirm unter "Regel erstellen" fort.

AWS IoT R1.png   2. Geben Sie einen beliebigen Regelnamen ein (in diesem Fall amzorderer), um die Regelabfrage festzulegen. Wenn eine Nachricht im Thema "amzordere" veröffentlicht wird, extrahiert sie den Wert des Elementattributs und führt die Aktion aus.

AWS IoT R2.png   3. Wählen Sie Call Lambda-Funktion als Aktion.

AWS IoT3.png   4. Die aufzurufende Funktion ist der zuvor erstellte "amzorderer".

AWS IoT R4.png   5. Klicken Sie auf "Regel erstellen", um die Erstellung abzuschließen.

AWS IoT R.png

3. Erstellen Sie ein Clientgerät

In diesem Kapitel verwenden wir Raspberry Pi, um ein Client-Gerät mit Schaltflächen zu erstellen.

Was ist Raspberry Pi Zero?

Unnötig zu sagen, dass es ein kleines Modell von Razpai sein wird. Mit einem CPU-Takt von 1 GHz und einem Speicher von 512 MB ist der Preis mit etwa 5 US-Dollar außergewöhnlich hoch. Diesmal mit diesem Raspberry Pi Zero, Ich möchte ein Gerät erstellen, das auf Knopfdruck eine Anfrage an AWS IoT sendet.

Dinge notwendig

Wir werden es mit grundlegenden elektronischen Arbeitsteilen machen, die in jedem Haushalt zu finden sind.

IMG_0307.JPG

Da es nur ein Mini-USB-Terminal gibt, ist es praktisch, zum Zeitpunkt der Ersteinstellung einen USB-Hub zu haben.

Grundeinstellung von Raspberry Pi (Betriebssysteminstallation)

Installieren Sie Raspbian (Jessie) unter Around here.

WLAN-Verbindung

Dieses Mal werden wir Raspberry Pi Zero über die drahtlose Slave-Einheit von Buffalo mit dem WLAN verbinden.

Schließen Sie die WLAN-Slave-Einheit an USB an. Wenn Sie den Befehl lsusb eingeben, können Sie sehen, dass er die Slave-Einheit erkennt.

$ lsusb
Bus 001 Device 002: ID 0411:01a2 BUFFALO INC. (formerly MelCo., Inc.) WLI-UC-GNM Wireless LAN Adapter [Ralink RT8070]
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Verwenden Sie den Befehl wpa_passphrase, um die für eine WLAN-Verbindung erforderliche SSID und das Kennwort zu generieren.

$ wpa_passphrase [SSID] [Passphrase]
network={
        ssid=[SSID]
        #psk=[Passphrase] <-Sie können diese Zeile löschen
        psk=[Verschlüsselte Passphrase]
}

Kopieren Sie den obigen Text und fügen Sie ihn zu / etc / wpa_supplicant / wpa_supplicant.conf hinzu.

/etc/wpa_supplicant/wpa_supplicant.conf


country=GB
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
        ssid=[SSID]
        psk=[Verschlüsselte Passphrase]
}

Bearbeiten Sie / etc / dhcpcd.conf und machen Sie es zu einer festen IP. Stellen Sie die IP-Adresse, den Router und das DNS entsprechend Ihrer Umgebung ein.

interface wlan0
static ip_address=192.168.11.30/24
static routers=192.168.11.1
static domain_name_servers=192.168.11.1

Wenn Sie die SSH-Verbindung vom Mutterschiff aus neu starten können, ist die Einstellung abgeschlossen.

$ sudo shutdown -r now

GPIO-Löten

Im Gegensatz zu anderen Modellen ist bei Verwendung von GPIO mit Raspberry Pi Zero das Löten erforderlich. Es wird eine feinere Arbeit sein als ich erwartet hatte, daher ist es besser, eine Lötausrichtung von φ0,6 mm zu verwenden.

IMG_0309.JPG

Baue eine Schaltung

Ehrlich gesagt ist elektronische Arbeit ein Amateur, aber ich werde sie unter Bezugnahme auf die Informationen erstellen, die ich im Internet gesucht habe. Das GPIO-Layout von Raspberry Pi Zero ist wie folgt.

Raspberry-Pi-Model-Zero-Mini-PC.jpg

Es nimmt eine Stromversorgung von 3,3 V von Nr. 1 und empfängt das Ein- und Ausschalten des GPIO25-Taktschalters bei GPIO9. Stecken Sie einen 10k Ohm Widerstand zwischen GPIO25 und GND. Dies wird als Pulldown-Widerstand bezeichnet und spielt eine Rolle bei der zuverlässigen Übertragung eines HIGH- (3,3 V) oder LOW- (0 V) Signals. Es tut mir leid, dass das Bild schwer zu verstehen ist.

S__2564101.jpg

Erstellen Sie ein Programm

Nachdem die Schaltung zusammengebaut ist, erstellen wir ein Programm, das die Eingabe des Taktschalters empfängt und die Nachricht an AWS IoT veröffentlicht.

Laufzeit

Python 2.7 ist in Raspbian (Jessie) installiert, daher werde ich das Programm in Python schreiben.

$ python -V
Python 2.7.9

Installation der erforderlichen Bibliotheken

Das Python SDK für die Verbindung mit AWS IoT ist für die Öffentlichkeit zugänglich und wird verwendet.

$ sudo pip install AWSIoTPythonSDK

Implementierung

publisher.py


# -*- coding:utf-8 -*-

__author__ = 'H.Takeda'
__version__ = '1.0.0'


from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
from argparse import ArgumentParser
import json
import logging
import RPi.GPIO as GPIO
import signal
import sys
import time


def configure_logging():
    # Configure logging
    logger = logging.getLogger("AWSIoTPythonSDK.core")
    logger.setLevel(logging.DEBUG)
    streamHandler = logging.StreamHandler()
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    streamHandler.setFormatter(formatter)
    logger.addHandler(streamHandler)


def parse():
    argparser = ArgumentParser()
    argparser.add_argument("-e", "--endpoint", type=str, required=True)
    argparser.add_argument("-r", "--rootCA", type=str, required=True)
    argparser.add_argument("-c", "--cert", type=str, required=True)
    argparser.add_argument("-k", "--key", type=str, required=True)
    args = argparser.parse_args()
    return vars(args)


def careate_client(endpoint, root_ca, cert, private_pey):
    # For certificate based connection.
    client = AWSIoTMQTTClient("raspi0")
    # Configurations
    client.configureEndpoint(endpoint, 8883)
    client.configureCredentials(root_ca, private_pey, cert)
    client.configureOfflinePublishQueueing(1)
    client.configureConnectDisconnectTimeout(10)    # 10 sec
    client.configureMQTTOperationTimeout(5)         # 5 sec
    return client


def handler(signum, frame):
    print "Signal handler called with signal", signum
    client.disconnect()
    GPIO.cleanup()
    sys.exit(0)


if __name__ == '__main__':
    # Parse command-line arguments.
    args = parse()
    # Configure logging
    configure_logging()
    # Create mqtt client.
    client = careate_client(
        args["endpoint"], args["rootCA"], args["cert"], args["key"])
    # Connect.
    client.connect()

    signal.signal(signal.SIGINT, handler)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(9, GPIO.IN)
    before = 0
    while True:
        now = GPIO.input(9)
        if before == 0 and now == 1:
            # Create message.
            message = {"item": "01"}
            # Publish.
            client.publish("amzorderer", json.dumps(message), 0)
            print "message published."
        time.sleep(0.1)
        before = now

Wir veröffentlichen eine Nachricht (Artikelklassifizierungswert "01" für den Kauf von Toilettenpapier) an AWS IoT, wenn GPIO 9 mit "RPi.GPIO" eingegeben wird.

Funktionsprüfung

Führen Sie das obige Skript auf Rapsberry Pi Zero aus und überprüfen Sie den Vorgang. Geben Sie den AWS IoT-Endpunkt, die Stammzertifizierungsstelle, das Clientzertifikat und den Pfad des privaten Schlüssels als Argumente für das Skript an. Obwohl dies in der README-Datei von AWS IoT SDK beschrieben ist, lautet die Stammzertifizierungsstelle hier. Erhalten von /content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem). Was ist ein Client-Zertifikat? Der private Schlüssel ist in der Zip-Datei enthalten, die beim Einrichten von AWS IoT heruntergeladen wurde.

$ python test.py -e <endpoint> -r <rootCA path> -c <certificate path> -k <private key path>
2016-12-11 08:15:31,661 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Paho MQTT Client init.
2016-12-11 08:15:31,664 - AWSIoTPythonSDK.core.protocol.mqttCore - INFO - ClientID: raspi0
2016-12-11 08:15:31,667 - AWSIoTPythonSDK.core.protocol.mqttCore - INFO - Protocol: MQTTv3.1.1
2016-12-11 08:15:31,672 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Register Paho MQTT Client callbacks.
2016-12-11 08:15:31,675 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - mqttCore init.
2016-12-11 08:15:31,680 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Load CAFile from: root-CA.crt
2016-12-11 08:15:31,683 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Load Key from: raspi0.private.key
2016-12-11 08:15:31,687 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Load Cert from: raspi0.cert.pem
2016-12-11 08:15:31,691 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Custom setting for publish queueing: queueSize = 1
2016-12-11 08:15:31,696 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Custom setting for publish queueing: dropBehavior = Drop Newest
2016-12-11 08:15:31,699 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Set maximum connect/disconnect timeout to be 10 second.
2016-12-11 08:15:31,704 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Set maximum MQTT operation timeout to be 5 second
2016-12-11 08:15:31,710 - AWSIoTPythonSDK.core.protocol.mqttCore - INFO - Connection type: TLSv1.2 Mutual Authentication
2016-12-11 08:15:32,384 - AWSIoTPythonSDK.core.protocol.mqttCore - INFO - Connected to AWS IoT.
2016-12-11 08:15:32,386 - AWSIoTPythonSDK.core.protocol.mqttCore - DEBUG - Connect time consumption: 70.0ms.

Als ich den Taktschalter drückte, wurde eine Nachricht an AWS IoT veröffentlicht und der Kauf von "Toilettenpapier" bei Amazon erfolgreich abgeschlossen.

Was ich machen wollte

Recommended Posts

"Amazon Dash Button" ist in Japan gelandet, aber ich habe es gewagt, es selbst zu machen
Als ich versuchte, eine VPC mit AWS CDK zu erstellen, konnte ich es aber nicht schaffen
Ich habe mein Bestes versucht, um eine Optimierungsfunktion zu erstellen, aber es hat nicht funktioniert.
Ich habe eine Amazon Web Service Dash-Schaltfläche erstellt
ForeignKey ist für CustomUser definiert, der in AUTH_USER_MODEL in Django angegeben ist, aber nicht referenziert wird.
Ich möchte mit einem Knopf am Kolben übergehen
Wie man Decorator in Django benutzt und wie man es macht
Python: Kann in Lambda wiederholt werden
Ich habe Schwarz in vscode eingeführt, aber es wird nicht automatisch formatiert