L'utilisation des téléphones portables à travers le monde est en constante augmentation. En 2013, environ 73% des utilisateurs d'Internet consommaient du contenu via un appareil mobile et ce pourcentage devrait atteindre près de 90% d'ici 2017.
Il y a, bien sûr, de nombreuses raisons à la révolution mobile. Mais l'un des plus importants est que les applications mobiles ont généralement accès à un contexte plus riche, car presque tous les smartphones sont aujourd'hui équipés de capteurs de localisation, de capteurs de mouvement, de Bluetooth et de wifi. En utilisant leurs données, les applications peuvent atteindre une «conscience du contexte» qui peut considérablement augmenter leurs capacités et leur valeur, et peut vraiment les faire se démarquer dans les magasins d'applications.
Dans ce didacticiel, nous allons explorer la création d'applications sensibles au contexte grâce à un exemple de traitement d'événements complexes. Nous allons utiliser un exemple assez simple: une application de prix du carburant qui trouve les meilleurs prix du carburant dans votre région.
Dans Concevoir la technologie Calm , Mark Weiser et John Seely Brown décrit technologie calme comme 'ce qui informe mais n'exige pas notre concentration ou notre attention.'
Les applications mobiles contextuelles sont très cohérentes avec cette notion et constituent une étape importante et précieuse dans cette voie. Ils utilisent des informations contextuelles glanées à partir de leurs capteurs pour fournir de manière proactive à l'utilisateur des informations précieuses et ils le font avec un minimum d'effort de la part de l'utilisateur. Mark Weiser et John Seely Brown applaudiraient sans aucun doute cette avancée technologique.
La connaissance du contexte est l'idée qu'une application peut détecter et réagir en fonction des données contextuelles auxquelles elle a accès. Une telle application utilise des données de capteur riches disponibles sur un appareil mobile pour fournir des informations précises et pertinentes à l'utilisateur dans le contexte approprié. Grâce aux tendances qu'elle observe au cours de l'utilisation de l'appareil et / ou grâce aux commentaires fournis par l'utilisateur, une telle application peut en fait «apprendre» au fil du temps, devenant ainsi «plus intelligente» et plus utile.
Traitement d'événements complexes (CEP) est une forme de traitement d'événements qui utilise des analyses plus sophistiquées de plusieurs événements (c'est-à-dire au fil du temps, de différentes sources, etc.), intégrant et analysant leur contenu pour en déduire des informations et des modèles plus significatifs.
Dans une application mobile, le CEP peut être appliqué aux événements générés à partir des capteurs de l'appareil mobile ainsi qu'aux sources de données externes auxquelles l'application a accès.
Pour les besoins de notre didacticiel de traitement d'événements complexes, supposons que les fonctionnalités de notre application de prix du carburant se limitent aux éléments suivants:
OK, commençons.
Commençons par la logique de détection automatique du domicile et du lieu de travail de l'utilisateur. Afin de simplifier les choses pour notre exemple de traitement d'événements complexe, nous allons supposer que l'utilisateur a un horaire de travail assez normal. On peut donc supposer que l'utilisateur sera généralement à la maison entre 2 et 3 heures du matin, et sera généralement à son bureau entre 14 et 15 heures.
Sur la base de ces hypothèses, nous définissons deux règles CEP et collectons les données de localisation et d'heure à partir du smartphone de l'utilisateur:
L'algorithme de haut niveau pour détecter les emplacements est décrit ci-dessous.
Supposons la structure de données JSON simple suivante pour les données de localisation:
qu'est-ce que le bootstrap en java
{ 'uid': 'some unique identifier for device/user', 'location': [longitude, latitude] 'time': 'time in user's timezone' }
Remarque: il est toujours recommandé de rendre les données de capteur immuables (ou de type valeur), afin qu'elles puissent être utilisées en toute sécurité par différents modules du flux de travail CEP.
Nous implémenterons notre algorithme en utilisant un modèle de module composable , dans lequel chaque module exécute une seule tâche et appelle ensuite lorsque la tâche est terminée. Ceci est conforme à l'Unix Règle de modularité philosophie.
Plus précisément, chaque module est une fonction qui accepte un config
objet et un next
fonction qui est appelée pour transmettre les données au module suivant. En conséquence, chaque module renvoie une fonction qui peut accepter des données de capteur. Voici la signature de base d'un module:
// nominal structure of each composable module function someModule(config, next) { // do initialization if required return function(data) { // do runtime processing, handle errors, etc. var nextData = SomeFunction(data); // optionally call next with nextData next(nextData); } }
Pour mettre en œuvre notre algorithme de déduction du domicile et du lieu de travail de l'utilisateur, nous aurons besoin des modules suivants:
Chacun de ces modules est décrit plus en détail dans les sous-sections qui suivent.
Notre filtre temporel est une fonction simple qui prend les événements de données de localisation en entrée et ne transmet que les données au next
module si l'événement s'est produit dans la tranche de temps qui vous intéresse. Le config
les données de ce module sont donc constituées des heures de début et de fin de la tranche de temps d'intérêt. (Une version plus sophistiquée du module pourrait filtrer en fonction de plusieurs tranches de temps.)
Voici une implémentation de pseudocode du module de filtre temporel:
function timeFilter(config, next) { function isWithin(timeval) { // implementation to compare config.start <= timeval <= config.end // return true if within time slice, false otherwise } return function (data) { if(isWithin(data.time)) { next(data); } }; }
La responsabilité de l'accumulateur est simplement de collecter les données de localisation pour ensuite être transmises au next
module. Cette fonction gère un compartiment interne de taille fixe pour stocker les données. Chaque nouvel emplacement rencontré est ajouté au compartiment jusqu'à ce que le compartiment soit plein. Les données de localisation accumulées dans le compartiment sont ensuite envoyées au module suivant sous forme de tableau.
Deux types de godets d'accumulateurs sont pris en charge. Le type de compartiment affecte ce qui est fait au contenu du compartiment une fois les données transmises à la phase suivante, comme suit:
Bucket de fenêtre tumbling (type = 'tumbling'
): après la transmission des données, vide le bucket entier et recommence à neuf (taille du bucket réduite à 0)
Type de fenêtre en cours d'exécution (type = 'running'
): après la transmission des données, ne supprime que l'élément de données le plus ancien du bucket (réduit la taille du bucket de 1)
Voici une implémentation de base du module accumulateur:
function accumulate(config, next) { var bucket = []; return function (data) { bucket.unshift(data); if(bucket.length >= config.size) { var newSize = (config.type === 'tumbling' ? 0 : bucket.length - 1); next(bucket.slice(0)); bucket.length = newSize; } }; }
Il existe bien sûr de nombreuses techniques sophistiquées en géométrie de coordonnées pour regrouper les données 2D. Voici un moyen simple de regrouper les données de localisation:
Voici une implémentation de cet algorithme de clustering (utilisant Lo-Dash
):
var _ = require('lodash'); function createClusters(location_data, radius) { var clusters = []; var min_points = 5; // Minimum cluster size function neighborOf(this_location, all_locations) { return _.filter(all_locations, function(neighbor) { var distance = distance(this_point.location, neighbor.location); // maximum allowed distance between neighbors is 500 meters. return distance && (500 > distance); } } _.each(location_data, function (loc_point) { // Find neighbors of loc_point var neighbors = neighborOf(loc_point, location_data, radius); _.each(clusters, function (cluster, index) { // Check whether some of the neighbors belong to cluster. if(_.intersection(cluster, neighbors).length){ // Expand neighbors neighbors = _.union(cluster, neighbors); // Remove existing cluster. We will add updated cluster later. clusters[index] = void 0; } }); if(neighbors.length >= min_points){ // Add new cluster. clusters.unshift(neighbors); } }); return _.filter(clusters, function(cluster){ return cluster !== void 0; }); }
Le code ci-dessus suppose l'existence d'un distance()
fonction qui calcule la distance (en mètres) entre deux emplacements géographiques. Il accepte deux points de localisation sous la forme de [longitude, latitude]
et renvoie la distance entre eux. Voici un exemple d'implémentation d'une telle fonction:
function distance(point1, point2) { var EARTH_RADIUS = 6371000; var lng1 = point1[0] * Math.PI / 180; var lat1 = point1[1] * Math.PI / 180; var lng2 = point2[0] * Math.PI / 180; var lat2 = point2[1] * Math.PI / 180; var dLat = lat2 - lat1; var dLon = lng2 - lng1; var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); var arc = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); var distance = EARTH_RADIUS * arc; return distance; }
Avec notre algorithme de clustering défini et implémenté (dans notre fonction createClusters()
ci-dessus), nous pouvons l'utiliser comme base pour notre module de clustering:
function clusterize(config, next) { return function(data) { var clusters = createClusters(data, config.radius); next(clusters); }; }
Toutes les fonctions des composants nécessaires sont maintenant définies, nous sommes donc prêts à coder nos règles de domicile / lieu de travail.
Voici, par exemple, une implémentation possible de la règle de localisation du domicile:
var CLUSTER_RADIUS = 150; // use cluster radius of 150 meters var BUCKET_SIZE = 500; // collect 500 location points var BUCKET_TYPE = 'tumbling'; // use a tumbling bucket in our accumulator var home_cluster = clusterize({radius: CLUSTER_RADIUS}, function(clusters) { // Save clusters in db }); var home_accumulator = accumulate({size: BUCKET_SIZE, type: BUCKET_TYPE}, home_cluster); var home_rule = timeFilter({start: '2AM', end: '3AM'}, home_accumulator);
Désormais, chaque fois que des données de localisation sont reçues d'un smartphone (via websocket, TCP, HTTP), nous transmettons ces données à home_rule
fonction qui à son tour détecte les clusters pour la maison de l'utilisateur.
L '«emplacement d'origine» de l'utilisateur est alors supposé être le centre du cluster d'emplacement d'origine.
Remarque: bien que cela puisse ne pas être tout à fait précis, cela convient pour notre exemple simple, d'autant plus que l'objectif de cette application est dans tous les cas simplement de connaître la zone entourant le domicile de l'utilisateur, plutôt que de connaître l'emplacement précis du domicile de l'utilisateur.
Voici un exemple de fonction simple qui calcule le «centre» d'un ensemble de points dans un cluster en faisant la moyenne des latitudes et des longitudes de tous les points de l'ensemble de cluster:
function getCentre(cluster_data) { var len = cluster_data.length; var sum = _.reduce(cluster_data, function(memo, cluster_point){ memo[0] += cluster_point[0]; memo[1] += cluster_point[1]; return memo; }, [0, 0]); return [sum[0] / len, sum[1] / len]; }
Une approche similaire pourrait être utilisée pour déduire le lieu de travail, la seule différence étant qu'elle utiliserait un filtre horaire entre 14 h et 15 h (par opposition à 2 h et 3 h du matin).
Notre application carburant est ainsi en mesure de automatiquement détecter les lieux de travail et de domicile de l’utilisateur sans aucune intervention de l’utilisateur. C’est l’informatique contextuelle à son meilleur!
Le travail acharné pour établir la connaissance du contexte a maintenant été fait, mais nous avons encore besoin d'une règle supplémentaire pour identifier les prix des stations-service à surveiller (c'est-à-dire quelles stations-service sont suffisamment proches du domicile ou du lieu de travail de l'utilisateur pour être pertinentes). Cette règle doit accéder à tous les emplacements des stations-service pour toutes les régions prises en charge par l'application de carburant. La règle est la suivante:
Cela peut facilement être mis en œuvre à l'aide de la fonction de distance indiquée précédemment comme filtre d'emplacement à appliquer à toutes les stations-service connues de l'application.
Une fois que l'application de carburant a obtenu la liste des stations-service préférées (c'est-à-dire à proximité) pour l'utilisateur, elle peut facilement rechercher les meilleurs prix de carburant dans ces stations. Il peut également avertir l'utilisateur lorsque l'une de ces stations-service a des prix ou des offres spéciales, en particulier lorsque l'utilisateur est détecté à proximité de ces stations-service.
Dans ce didacticiel de traitement d'événements complexe, nous avons à peine effleuré la surface de l'informatique contextuelle.
que veut dire le chapitre 11
Dans notre exemple simple, nous avons ajouté un contexte de localisation à une application de rapport de prix du carburant par ailleurs simple et l'avons rendue plus intelligente. L'application se comporte désormais différemment sur chaque appareil et détecte au fil du temps les modèles de localisation pour améliorer automatiquement la valeur des informations qu'elle fournit à ses utilisateurs.
Sûrement beaucoup plus de données logiques et de capteurs peuvent être ajoutées pour augmenter la précision et l'utilité de notre application contextuelle. UNE développeur mobile intelligent pourrait, par exemple, utiliser les données des réseaux sociaux, les données météorologiques, les données de transaction du terminal de point de vente, etc. pour ajouter encore plus de prise en compte du contexte à notre application et le rendre plus viable et commercialisable .
Avec l'informatique contextuelle, les possibilités sont infinies. De plus en plus d'applications intelligentes continueront d'apparaître dans les magasins d'applications qui utilisent cette technologie puissante pour nous simplifier la vie.