Blog

Game of things: magento button [part 1/2]

Lettura 7 minuti

Da qualche anno ormai l’acronimo IOT (Internet of things) è sempre più popolare. Per IOT si intende la rete dei dispositivi in grado di accedere ad Internet. Un oggetto connesso ad internet potrebbe essere ad esempio un igrometro, una pompa di calore, ma anche un sistema più complesso come una casa oppure l’insieme dei sensori di un oleodotto.

“L’Internet delle cose è una possibile evoluzione dell’uso della Rete: gli oggetti (le “cose”) si rendono riconoscibili e acquisiscono intelligenza grazie al fatto di poter comunicare dati su se stessi e accedere ad informazioni aggregate da parte di altri. Le sveglie suonano prima in caso di traffico, le scarpe da ginnastica trasmettono tempi, velocità e distanza per gareggiare in tempo reale con persone dall’altra parte del globo, i vasetti delle medicine avvisano i familiari se si dimentica di prendere il farmaco. Tutti gli oggetti possono acquisire un ruolo attivo grazie al collegamento alla Rete.” (Wikipedia)

Ma veniamo a noi, cosa c’entra Magento in questo discorso?

Giorni fa mi sono trovato in un negozio in stazione, ho provato delle scarpe. Avrei voluto comprarle ma poiché non avevo spazio (e volontà) per portarle dietro ho abbandonato l’idea. In questo caso sarebbe stato interessante per me se il canale fisico e quello web del negozio fossero stati integrati. In treno, successivamente, pensavo che un dispositivo fisico che avesse fatto da trigger per l’Add to cart sullo store web avrebbe potuto risolvere il problema. Se avessi potuto trasferire dal canale fisico a quello web il mio interesse, successivamente dal treno o da casa avrei potuto ordinare e pagare l’oggetto e riceverlo in un secondo momento.

L’idea è quella dei single-purpose buttons. In sostanza il button è programmato (eventualmente pre-configurato) per eseguire un’azione predeterminata. L’assunzione è che si riesca ad autenticare il customer per utilizzare il suo carrello.

In questa primo post introdurrò solo la parte strettamente software, ovvero l’interfaccia su protocollo MQTT all’api di Magento. Per connettere il button fisico a Magento ci serviremo degli strumenti di AWS. Come da qualsiasi ricetta partiamo dagli ingredienti:

Software

  • Arduino IDE
  • AWS IOT e AWS Lambda
  • Magento 2

AWS IOT

“AWS IoT è una piattaforma cloud gestita che consente a dispositivi connessi di interagire in modo semplice e sicuro con applicazioni nel cloud e altri dispositivi. AWS IoT è in grado di supportare miliardi di dispositivi e migliaia di miliardi di messaggi, ed è in grado di elaborare e instradare tali messaggi agli endpoint di AWS e ad altri dispositivi in modo sicuro e affidabile. Con AWS IoT, le applicazioni rimangono collegate e comunicano con tutti i dispositivi, in qualsiasi momento, anche quando non sono collegati.” la descrizione da amazon.com.

AWS IOT è un ecosistema di strumenti che consente a versioni cloud di oggetti di interagire tra di loro e con il mondo esterno (e ovviamente con il resto di AWS), seguendo delle regole (rules).

AWS IOT consente di creare oggetti o Things che potrebbero essere visti come degli alter ego cloud degli oggetti fisici, ne mantengono lo stato e rispondono agli eventi. Ogni Thing ha un endpoint RESTful su protocollo HTTP e una serie di endpoint per poter soddisfare il protocollo di messaggistica leggero MQTT. Non approfondisco ma il protocollo MQTT e AWS IOT meritano qualche lettura.

Quello che ci interessa è creare una Thing che rappresenterà il pulsante fisico che andremo a creare. Dalla console di AWS IOT sotto Resigstry > Things è possibile trovare le Things già create. In alto a destra Create per crearne una nuova.

Creiamo la nostra Thing. Per semplicità la chiamerò semplicemente button. Per poter organizzare/categorizzare le Things si possono creare dei tipi Registry > Types.

Quando creata, la Thing sarà accessibile dal registro. Cliccandoci sopra andremo ad una pagina di gestione dell’oggetto. Particolarmente interessanti sono le sezioni Shadow, Interact e Activity. In Shadow si può vedere lo stato attuale dell’oggetto nel cloud. In Interact si sono i diversi EndPoints RESTful e MQTT. In Activity si possono vedere le interazioni con l’oggetto, i messaggi scambiati e le variazioni di stato. In questa fase il log sarà vuoto, in una fase attiva dell’oggetto la pagina Activity si presenterà così:

Nell’esempio dello screenshot si può vedere che è stato richiesto un update dello stato e l’oggetto JSON state rappresenta il nuovo stato. Ad ogni click il button fisico farà un update dello shadow passando i parametri necessari all’Add To Cart (da notare che non ci sono parametri riguardanti il customer che per semplicità dell’esempio è stato cablato nella funziona Lambda). In questo modo la Thing potrebbe rappresentare l’insieme dei button fisici dello store riutilizzando lo state per parametrizzare la richiesta.

I parametri, ovvero il prodotto che rappresenta, saranno pre-programmati nel button fisico, mentre per ora non è stata implementata alcuna logica per l’autenticazione.

AWS Lambda

La logica di connessione tra l’ecosistema dei buttons e Magento è stata affidata ad una funziona AWS Lambda. Non mi soffermo su Lambda. In seguito il codice per l’add to cart.

La funzione si occupa di fare il login, recuperare il carrello e aggiungere l’item. Per farlo utilizza le API REST di Magento 2. In termini architetturali probabilmente si potrebbe migliorare, magari scomporla, ma per l’esempio è più pratica così.

var request = require('request');
exports.handler = (event, context, callback) => {
  var data = JSON.stringify(event, null, 2);
  data = JSON.parse(data);
  data = data.state.reported;
    
  console.log("Received event:", data);
  
  var baseUrl = 'http://casa-riccardo.ddns.net/index.php/rest/V1/';
  var urlToken = baseUrl+'integration/customer/token';
  var urlCart = baseUrl+'carts/mine';

  request({ // first request: login
      url: urlToken,
      method: "POST",
      headers: {
        "content-type": "application/json",
      },
      // TODO replace with dynamic auth
      body: '{"username": "roni_cost@example.com","password": "roni_cost3@example.com"}'
    }, function (error, response, body) { // second request retrieve quote_id
      if (!error && response.statusCode === 200) {
        var token = "Bearer "+JSON.parse(body);
        console.log("token: "+token);
        console.log(urlCart);
        request({
          url: urlCart,
          method: "GET",
          headers: {
            "content-type": "application/json",
            "authorization": token,
          }
        }, function(error, response, body){ // third request add to cart
          if (!error && response.statusCode === 200) {
            var cart = JSON.parse(body);
            request({
                url: baseUrl+'carts/mine/items',
                method: "POST",
                headers: {
                  "content-type": "application/json",
                  Authorization: token,
                },
                body: '{"cartItem": {"sku": "'+data.sku+'", "qty": "'+data.qty+'","name":"'+data.name+'","product_type":"'+data.product_type+'","quote_id": "'+cart.id+'"}}'
              }, function(error, response, body){
                // TODO handle error
                console.log(body);
              }
            );
          }
          else {
            // TODO handle error
            console.log(response.statusCode);
          }
        });
      }
      else {
        // TODO handle error
        console.log(response.statusCode);
      }
    }
  );
};

Poiché la funzione utilizza request, per poterla far girare bisogna scaricarne lo zip dalla console di Lambda e con npm installare la dipendenza request, zippare di nuovo il tutto compresa la cartella _nodemodules e fare l’upload.

(come si vede la logica di autenticazione va completamente sviluppata, per ora la funzione Lambda ha all’interno una cablatura con i dati. Non mi soffermerò in questo post)

Connettere Thing e Lambda

Per poter far girare la funzione Lambda ad ogni update dello stato bisogna creare una rule che farà da trigger. La rule va configurata come in basso.

La logica con cui selezionare gli update di stato andati a buon fine è abbastanza semplice. Unico punto a cui fare attenzione è il topic da monitorare, i topic possibili sono quelli visti nella pagina di configurazione della Thing sotto la voce Interact.

Continua…

A questo punto la controparte cloud del button è completa e testabile indipendentemente dal device fisico.

La funzione Lambda è atomica e può essere testata dalla console di AWS. Nella pagina della funzione, click su Test popoliamo come nell’immagine in basso, _Save & Test_ e la funzione sarà eseguita.

Se tutto è andato a buon fine nel carrello di Magento ci sarà uno zaino in più.

Se non ha funzionato in Cloud Watch di AWS sotto Logs ci saranno i log della funzione Lambda. Per testare invece la Thing, nella pagina del button scheda _Activity > MQTT Client _possiamo fare _Publish_ sul topic monitorato dalla rule $aws/things/button/shadow/update/accepted. L’input è lo stesso JSON dell’input della funzione Lambda.

Publish to topic: il publish esaudirà la query della Rule che sarà il trigger della funzione Lambda, risultato ci sarà un nuovo zaino nel carrello di Magento dell’utente demo.

Nel prossimo post vedremo come realizzare il button fisico con ESP8266 e Arduino IDE.

Riccardo Cioria