The Retail Revolution - Antonio Nappi & Enzo Carrea - Codemotion Milan 2016

Preview:

Citation preview

The Retail RevolutionAntonio Nappi & Enzo Carrea

Indra & Tim Foundry

Questo Prototipo nasce da un accordo di collaborazione siglato tra Tim ed Indra per lo sviluppo congiunto di soluzioni innovative nell’ambito dell’Internet of things e delle smart solutions.  

Il prototipo è stato sviluppato all’interno dell’officina dell’innovazione “TIM Foundry”, dove si identificano e sperimentano le soluzioni più innovative nel settore della digital life.

Indice

• Dall’idea al prototipo• Proximity Marketing• Beacon• Le nostre scelte• Il prototipo• L’app• Stack Software• Nativa, Ibrida o Html

5

• Cordova• I plugin Cordova• Angular JS• Code Snippet• Sofia• Dashboard & Sofia• Dashboard Code

Snippet• Demo

Di cosa Parleremo

Dall’idea al prototipo

Qual è la differenza tra uno Store Fisico ed uno Store Online?Come può aumentare la produttività ed incrementare i clienti?

Quali dati possiamo raccogliere in uno Store Fisico?

Una tecnica di marketing che opera su un’area geografica delimitata e precisa attraverso tecnologie di comunicazione di tipo visuale e mobile con lo scopo di promuovere la vendita di prodotti e servizi. (Wikipedia)

Proximity Marketing

I Beacon, sono dei dispositivi che grazie alla tecnologia Bluetooth 4.0 Smart Low Energy, possono interagire con periferiche e dispositivi senza impieghi energetici eccessivi. La tecnologia si presenta come un sistema di proposta contestuale di contenuti basati su microgeolocalizzazione. 

Un sensore iBeacon definisce un'area il cui raggio varia da 20cm fino ad un massimo di 70 metri (all’aria aperta). Ogni dispositivo, dotato di un'apposita app, può, determinare il grado di prossimità e “scatenare” un azione

Beacon

I Beacon definiscono una Regione e sono identificata dalla seguente tripletta:

• UUID: (Universally Unique Identifier) – stringa che identifica I beacon

• Major: identifica un beacon e può essere comune a più beacon in una regione

• Minor: identifica un beacon e può essere unico nella stessa regione

Beacon

Abbiamo usato i beacons Estimote perché offrivano delle api multipiattaforma ed maggiormente documentati e supporati dalla community

http://developer.estimote.com/ibeacon/

APIestimote

Le nostre scelte

Angular come framework per il nostro prototipo

Librerie Javascript utilizzate• BlueImp per i carousel• OnSen per rendere compliant le due

soluzioni iOS ed Android• SwetAlert, Stroll

Angular JS

<body ng-controller="AppController" ontouchstart="myEstimote.onTouchStart(event);" ontouchmove="myEstimote.onTouchMove(event);" ontouchcancel="myEstimote.onTouchCancel(event);"> <ons-navigator var="myNavigator"><ons-page ng-controller="MasterController" ng-device-backbutton="exitApp()"> <ons-toolbar fixed-style> <div class="center"></div> <div class="right"> <ons-button ng-click="showSettings()" class="settings-btn btnCustom"> <ons-icon icon="ion-android-settings" fixed-width="true"></ons-icon> </ons-button> <ons-button onClick="callRetailer()" class="shopping-cart-btn btnCustom"> <ons-icon icon="ion-android-person" fixed-width="true"></ons-icon> </ons-button> <ons-button ng-click="showShoppingCart()" class="shopping-cart-btn btnCustom"> <ons-icon icon="ion-android-cart" fixed-width="true"></ons-icon> <span class="shopping-cart-counter">{{getCartCounter()}}</span> </ons-button> </div> </ons-toolbar> <div> <div align="center"> <img src="img/tim_proximity_logo6.png" alt="TIM Logo" width="200" height="100" align="middle" style="margin: 20px auto;"> </div> <div align="center"> <ons-button class="circle-button grow" ng-click="startRanging()" style="margin-top: 70px !important;"> CERCA </ons-button>

Code SnippetPresentation

$("#loading_label").show(); $scope.items = {}; $scope.ons.navigator.pushPage('offers.html', { title: "Offerte", onTransitionEnd: function () { // startStroll(); } }); beaconInRange = false; if (IS_ANDROID || IS_IPHONE) { myEstimote.onStartRanging(); }

function onRange() var beaconVincitore = beaconInfo.beacons[0];$.each(beaconInfo.beacons, function(key, beacon)

{if(beacon.distance < beaconVincitore.distance){

beaconVincitore = beacon;}

});onBeaconRange(beaconVincitore);

EstimoteBeacons.startRangingBeaconsInRegion({}, // Empty region matches all beacons.onRange,onError);

function onStartRangin ()

function startRanging()

Logic

Code Snippet

…if(beacon.minor == beaconMin && beacon.major == beaconMaj) { beaconLastRangeTime = new Date().getTime(); br = beacon.distance; posElement = search('B04',mapBeaconPOI); idPoi = mapBeaconPOI[posElement].idPoi; idCategoria = mapBeaconPOI[posElement].cat; descrizione = mapBeaconPOI[posElement].descrizione; if (!beaconInRange && (beacon.proximity == 2 || beacon.proximity == 3) && myNavigator.getCurrentPage().page == "offers.html") { swal(frasiCategorie[idCategoria-1][0]); SetObjBeaconData(UUIDApp,"BO4",idPoi,descrizione,beacon.proximity); if (VIBRATION_SETTING_ENABLE) navigator.vibrate(1000); resetIsBaeconInRange(); beaconInRange = true; angular.element($("#offersControllerId")).scope().refreshList(idCategoria); } if (beaconInRange && beacon.proximity == 1 && (currTime - lastImmediateOfferPushTime) > 4000 && myNavigator.getCurrentPage().page == "offers.html") { lastImmediateOfferTime = new Date().getTime(); currentImmediateOfferId = 4; SetObjBeaconData(UUIDApp,"BO4",idPoi,descrizione,beacon.proximity); if (VIBRATION_SETTING_ENABLE) navigator.vibrate(1000); lastImmediateOfferPushTime = new Date().getTime(); angular.element($("#offersControllerId")).scope().showDetailFromBeacon(idCategoria, idPoi); } } …

function onBeaconRange(beacon)

Logic

Code Snippet

… var currTime = new Date().getTime(); if (beacon1InRange && (currTime - beacon1LastRangeTime) > 5000) { beacon1InRange = false; } if (beacon2InRange && (currTime - beacon2LastRangeTime) > 8000) { beacon2InRange = false; posElement = search('B02',mapBeaconPOI); idPoi = mapBeaconPOI[posElement].idPoi; idCategoria = mapBeaconPOI[posElement].cat; swal(frasiCategorie[idCategoria-1][1]); angular.element($("#offersControllerId")).scope().refreshList(); } }…

function checkBeaconOutOfRange()

…checkBeaconOutOfRange();sendBeaconDataTimer += deltaTime;if (sendBeaconDataTimer >= intervallo) { // in secondssendBeaconDataTimer = 0;sendBeaconData(); }…

function update()Logic

Code Snippet

var jsonData = { Feed:{ idApp:UUIDApp, intervallo:intervallo, dateTime: data, idBeacon: idBeacon, idPOI: idPoi, descrizione:descrizione, range: proximity, isEnabled: true } }; $.ajax({ url:'http://130.211.88.57/sib-api/api/v1/feedretailbeaconsdatait', type:'POST', dataType:'json', contentType:'application/json', headers:{ 'Accept':'application/json, text/javascript', 'X-SOFIA2-APIKey':'172f6f768a614da1b1c8abea9ee44fbd' }, data:JSON.stringify(jsonData), success: function(data){ console.log(data);},

function sendBeaconData()

Feed

Code Snippet

I dati raccolti dall’ Applicazione Mobile vengono inviati a Sofia anche per generare una pubblicità personalizzata per l’utente che si avvicina alla Cassafunction sendBeaconDataCart(){

Feed:{ idEvent:"Cassa", idApp:UUIDApp, dateTime: data, last_instance:2, infos:"string", } };$.ajax({ url:'http://130.211.88.57/sib-api/api/v1/feedretaileventit', type:'POST', dataType:'json', contentType:'application/json', headers:{ 'Accept':'application/json, text/javascript', 'X-SOFIA2-APIKey':'172f6f768a614da1b1c8abea9ee44fbd' }, data:JSON.stringify(jsonData)…..

Code Snippet

FEEP IoT Platform SOFIA2

Tutti i dati raccolti dall’app vengono caricati tramite Sofia in un database NoSql Mongo. La Dashboard sviluppata in Angular effettua delle query Mongo sul Database per ottenere i Dati da mostrare

Le query mongo vengono gestite tramite la libreria javascript di Sofia reperibile dal Sito sofia2.com

Dashboard Code Snippet

function loadNumberOfUserInStoreActual(ssapMessageJson){

if(ssapMessageJson===null || ssapMessageJson===undefined){console.log('impossibile recuperare i dati: null json message');} else { if(ssapMessageJson.body.data===null || ssapMessageJson.body.data === undefined) return; if(ssapMessageJson.body.data.length>0) { var _numeroUtenti = ssapMessageJson.body.data[0].numeroUtenti; _scope.numeroUtentiNelloStoreActual = _numeroUtenti; } } _scope.$digest();

… var queryMongo = "db.feedRetailBeaconsData.aggregate([" + "{'$match':{'Feed.dateTime':{'$gte': '"+_date+"'}}}," + "{'$project':{'Feed.idApp':1,'Feed.dateTime':1,'x':1}}," + "{'$group': {'_id':'$Feed.idApp'}}," + "{'$group': {'_id':'$x', 'numeroUtenti':{'$sum':1} } }," + "{'$project':{'_id':1,'numeroUtenti':1}} " + "])";

sofia2.queryWithQueryType ( queryMongo, ontoSmartRetail, "NATIVE", null, loadNumberOfUserInStoreActual);….

Esempio di codice per la richiesta del dato Utenti Fidelizzati nello store.