Système de stationnement intelligent avec suivi de l'espace en direct
Published: 2024-01-11 12:23:57

Jamais auparavant nous n'avons vécu à une époque où chaque "chose" pouvait être interconnectée de manière transparente par l'internet. L'idée de l'[internet des objets (IdO](https://www.pubnub.com/solutions/iot-device-control/) ) a continuellement transformé notre monde en apportant des solutions innovantes à de nombreux problèmes à l'aide d'une **architecture Pub/Sub pilotée par les événements**. Par exemple, pour résoudre le problème épuisant de la recherche d'une place de stationnement dans des espaces bondés, les parkings ont installé des tableaux de bord électroniques en direct indiquant les places disponibles en s'abonnant aux mises à jour d'état publiées par des capteurs individuels dans un parc de stationnement. La création d'une telle application IoT peut s'avérer difficile en raison d'un certain nombre d'obstacles.

L'un de ces obstacles est l'hébergement d'un serveur capable de traiter en temps réel les messages envoyés entre l'application mobile et les capteurs. Un autre obstacle est l'hébergement d'un réseau wifi capable de prendre en charge chaque capteur intégré dans le parking intelligent.

En utilisant **PubNub** et **Soracom** l'un à côté de l'autre, les développeurs peuvent rapidement contourner ces défis. Avec la plateforme temps réel de PubNub, les développeurs peuvent facilement [construire des solutions IoT complexes](https://www.pubnub.com/solutions/iot-device-control/) pour la [surveillance des véhicules](https://www.pubnub.com/solutions/transport-delivery/) sans se soucier de tâches fastidieuses telles que l'hébergement de serveurs. De plus, avec [Soracom Air](https://www.soracom.io/products/air/) et [Soracom Beam](https://www.soracom.io/products/beam/), les développeurs peuvent facilement créer des solutions IoT qui utilisent le LTE, au lieu d'un réseau WFI restrictif.

Vue d'ensemble du tutoriel
--------------------------

Dans ce tutoriel, nous allons construire une simulation de parking intelligent en utilisant Raspberry Pi et un capteur à ultrasons pour détecter si une place de parking est occupée ou vacante. Nous utiliserons Soracom Air pour envoyer des messages du capteur à PubNub via des données cellulaires. Ensuite, en utilisant l'API Publish-Subscribe de PubNub, nous rendrons les données de stationnement instantanément disponibles à tous les utilisateurs mobiles de l'application. Ceci est illustré dans le diagramme suivant.

* * *

**Pour le code source complet, [cliquez ici](https://github.com/PubNubDevelopers/Smart-Parking)**.

* * *

[![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja5/9d106e47efa5221bc12537d32cfa2d3a/screenshot.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja5/9d106e47efa5221bc12537d32cfa2d3a/screenshot.png)

Pour construire cette démo, vous aurez besoin de :

1.  Raspberry Pi (toute version)
2.  Planche à pain
3.  Capteur ultrasonique HC-SR04
4.  1 fil de liaison femelle-femelle + 6 fils de liaison mâle-femelle
5.  1 résistance de **1k Ω** et 1 résistance de **2k Ω**
6.  Carte MicroSD + adaptateur MicroSD vers SD
7.  Clé USB modem Huawei
8.  Carte Sim Soracom Air

Raspberry Pi Setup
------------------

### **1\. Installation du système d'exploitation Raspbian**

Si vous ne l'avez pas encore fait, assurez-vous d'installer le système d'exploitation Raspbian sur votre Raspberry Pi. Pour ce faire, nous allons d'abord l'installer localement sur notre ordinateur. Il s'agira d'une image disque, nous devrons donc flasher le disque avant de l'utiliser. Vous pouvez utiliser [Etcher](https://www.balena.io/etcher/) pour flasher le disque sur votre carte microSD Adapter.

[![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja6/56bde9961fc7faffc78d276cc5dd8916/Screen-Shot-2018-07-31-at-12.47.07-PM.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja6/56bde9961fc7faffc78d276cc5dd8916/Screen-Shot-2018-07-31-at-12.47.07-PM.png)

Une fois que les fichiers du système d'exploitation Raspbian sont sur notre adaptateur de carte microSD, nous pouvons retirer la carte microSD de l'adaptateur et l'insérer dans la fente inférieure de notre Raspberry Pi. Une fois le système d'exploitation installé, vous pouvez maintenant démarrer le Raspberry Pi en branchant un clavier, une souris, un écran et une source d'alimentation.

### 2\. Configurer le capteur

[![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja7/9791eceb9d4aa6d43903901e40097b21/Screen-Shot-2018-07-31-at-1.45.55-PM.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja7/9791eceb9d4aa6d43903901e40097b21/Screen-Shot-2018-07-31-at-1.45.55-PM.png)

1.  Brancher 3 de nos **fils de connexion mâle-femelle** dans le **capteur ultrasonique HC-SR04** dans les **emplacements VCC, Echo, et GND.** Brancher un de nos **fils de connexion femelle-femelle** dans l'emplacement **Trig** du capteur.
2.  Branchez le **fil** **VCC** dans le **rail positif de** notre planche à pain et le **fil** **GND** dans le **rail négatif**.
3.  Branchez le **GPIO 5V** du Raspberry Pi sur le **rail positif** de notre carte à pain et le **GPIO GND** sur le **rail négatif**.
4.  Branchez le **fil Trig** sur le **GPIO 23**.
5.  Branchez le **fil Echo** sur un **rail vierge** de la planche à pain.
6.  Reliez un autre rail vierge à l'aide d'une **résistance de 1k Ω.**(La raison pour laquelle nous avons besoin de résistances est que nous pouvons réduire la tension de sortie pour nous assurer que notre Raspberry Pi n'est pas endommagé par la configuration du capteur).
7.  Reliez ensuite un rail vierge à l'aide d'une **résistance de 2k Ω** au rail négatif de notre planche à pain en laissant un espace. Si vous n'avez pas de résistance de 2k Ω, vous pouvez créer une série de 2 résistances de 1k Ω, comme le montre l'image suivante.[![IMG_20180731_151118-1](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja9/1c9c8a5ed42e0d91b802e6dd117bcd1a/IMG_20180731_151118-1.jpg "IMG_20180731_151118-1")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1ja8/3f8e169838914d011b94fa213f65b1b7/IMG_20180731_151118-1.jpg)
8.  Dans l'espace restant, nous utiliserons un **fil de liaison mâle-femelle** pour relier le **GPIO 24**.

Félicitations, nous avons maintenant terminé la configuration de notre capteur à ultrasons. Si vous n'arrivez pas à configurer le capteur, consultez ce [tutoriel](https://thepihut.com/blogs/raspberry-pi-tutorials/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi) pour une explication plus détaillée. Pendant que vous construisez votre circuit, rappelez-vous que sur les rails vierges [de la planche à pain](https://en.wikipedia.org/wiki/Breadboard), le courant circule horizontalement et sur les rails positifs et négatifs de la planche à pain, le courant circule verticalement. Ensuite, nous allons configurer PubNub et Soracom dans notre application IoT.

Configuration de PubNub
-----------------------

Tout d'abord, nous allons créer notre application dans la [console d'administration PubNub](https://dashboard.pubnub.com/login)**(c'est gratuit**). Après avoir créé l'application dans la console, vous verrez les clés de publication et d'abonnement que nous utiliserons dans l'étape suivante pour connecter PubNub et Soracom.

Configuration de la Soracom
---------------------------

### **Enregistrer la carte SIM**

Nous allons nous rendre sur la [console d'administration de Soracom](https://console.soracom.io/). Ici, nous cliquerons sur **Enregistrer SIM** et entrerons les chiffres **ICCID** et **PUK**, que vous trouverez au dos de votre **carte Sim Soracom Air**.

[![imageedit_2_3979299183](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jab/26b73ca8e719f9eaf8cc42ea2c631087/imageedit_2_3979299183.png "imageedit_2_3979299183")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jaa/2dcb1f4a63420c662d7dbcf859027a23/imageedit_2_3979299183.png)[![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jac/d927cf8efc47161a592fd4ea756a69d5/Screen-Shot-2018-07-31-at-3.47.58-PM.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jac/d927cf8efc47161a592fd4ea756a69d5/Screen-Shot-2018-07-31-at-3.47.58-PM.png)

### Configuration du modem USB

Après avoir enregistré notre carte SIM, nous allons retirer la puce SIM (représentée par le cercle violet que j'ai dessiné autour d'elle dans l'image ci-dessus). Nous allons ensuite l'insérer dans la **clé USB modem Huawei**. Assurez-vous que vous avez glissé la carte SIM jusqu'au bout, le bon côté vers le haut.

[![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jad/dddd1f8435888122020be80479bfe8de/Screen-Shot-2018-08-01-at-11.21.56-AM.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jad/dddd1f8435888122020be80479bfe8de/Screen-Shot-2018-08-01-at-11.21.56-AM.png)

Pour que notre Raspberry Pi fonctionne avec des données cellulaires, il suffit de brancher la [clé USB modem Huawei](https://consumer.huawei.com/en/routers/e3372/specs/) sur le port USB du Raspberry Pi. Une **lumière bleue fixe** (qui ne clignote pas) indique que le modem capte avec succès les données 3g. S'il clignote, cela signifie qu'il tente toujours de se connecter.

[![IMG_20180801_141334](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jaf/445f100919feb6626cc4f1167b36f290/IMG_20180801_141334.jpg "IMG_20180801_141334")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jae/a9574a8b0e9a08f80e430d03605c3bbd/IMG_20180801_141334.jpg)

Une fois la lumière bleue allumée, nous devons ajouter notre modem clé USB au gestionnaire de réseau du Raspberry Pi. Pour ce faire, installez d'abord le gestionnaire de réseau sur le Raspberry Pi. Dans le terminal de votre Raspberry Pi, tapez ce qui suit.

```js
sudo apt-get update && sudo apt-get install network-manager
```

Ensuite, pour connecter notre clé USB à notre compte Soracom, nous devons taper la commande suivante dans le terminal de notre Raspberry Pi. Remplacez **<ENTER\_USERNAME>** et **<ENTER\_PASSWORD>** par vos identifiants de compte respectifs.

```js
sudo nmcli con add type gsm ifname "*" con-name soracom apn soracom.io user <ENTER_USERNAME> password <ENTER_PASSWORD>
```

Pour que cette configuration soit prise en compte, nous devons redémarrer notre Raspberry Pi.

```js
sudo reboot
```

Maintenant, pour vous assurer que votre modem USB est reconnu par le gestionnaire de réseau de votre Raspberry Pi, tapez :

```js
ifconfig
```

Vous devriez voir apparaître un

```js
ppp0
```

(votre modem USB). Tapez ensuite les 3 commandes suivantes pour vous assurer que vous avez téléchargé le script ppp route metric de Soracom et que le script est exécuté à chaque fois que le modem USB est branché ou redémarré.

```js
sudo curl -o /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric https://soracom-files.s3.amazonaws.com/handson/90.set_ppp_route_metric
```

```js
sudo chmod +x /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric
```

```js
sudo /etc/NetworkManager/dispatcher.d/90.set_ppp_route_metric ppp0 up
```

Maintenant, notre modem clé USB devrait être correctement configuré. Si vous n'arrivez toujours pas à configurer le modem clé USB, lisez attentivement la [documentation de Soracom](https://github.com/soracom/handson/wiki/1.3.-USB-Dongle-configuration-tutorial-(SIM-pre-registered)).

### Configuration MQTT

[**MQTT**](https://www.pubnub.com/guides/mqtt/) (Mosquitto) est le nom du protocole que nous allons utiliser pour publier des messages sur notre canal PubNub depuis l'application Raspberry Pi IoT. Dans la console d'administration, nous allons ouvrir le lien de la barre de navigation latérale intitulé Groupes pour **ajouter un nouveau groupe**. Nous appellerons ce nouveau groupe **Beam-Soracom**. Dans les paramètres de base de ce nouveau groupe, cliquez sur **Soracom Beam**. Ici, nous allons créer un **point d'entrée MQTT**. Assurez-vous que les éléments suivants ont été saisis lors de la création du point d'entrée [MQTT](https://www.pubnub.com/blog/what-is-mqtt-use-cases/). Vous devrez spécifier que le type de destination est **PubNub**. Là où vous voyez **Credentials Set**, nous allons ajouter nos Credentials [PubNub](https://admin.pubnub.com/#/register)**(Publish et Subscribe Key**) pour permettre à notre appareil Soracom de publier des messages sur notre canal PubNub.

[![IMG_20180801_141334](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jag/91b258ac62700455e397540e39711e13/Screen-Shot-2018-07-31-at-3.55.03-PM.png "IMG_20180801_141334")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jag/91b258ac62700455e397540e39711e13/Screen-Shot-2018-07-31-at-3.55.03-PM.png)

Ensuite, nous allons sélectionner notre carte SIM enregistrée dans la console d'administration et définir son groupe à celui que nous venons de créer, appelé **Beam-Soracom**. Assurez-vous que vous avez cliqué sur **activer** sur notre carte SIM enregistrée, de sorte qu'elle soit active et qu'elle capte des données.

Nous devons maintenant installer le paquet **mosquitto-clients** sur notre Raspberry Pi, afin de pouvoir utiliser la méthode de publication de MQTT. Dans le terminal du Raspberry Pi, exécutez la commande suivante.

```js
sudo apt-get update && sudo apt-get install mosquitto-clients
```

Une fois mosquitto-clients installé, nous pouvons tester notre commande **mosquitto\_pub**, que nous utiliserons pour publier un message sur notre canal PubNub. Le format de notre commande mosquitto\_pub sera le suivant. Après **\-t**, nous insérerons le nom de notre canal, **parking\_spot**. Et après **\-m**, nous insérerons un message de test "test". Ouvrez votre Debug View sur la console d'administration PubNub. Une fois que vous avez exécuté la commande ci-dessous sur le terminal du Raspberry Pi, vous devriez voir que le message a été publié avec succès sur notre canal PubNub.

```js
mosquitto_pub -h beam.soracom.io -p 1883 -t parking_spot  -m "test"
```

[![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jah/c9c174db5a0b05b0f6e55c495a2a30fd/Screen-Shot-2018-08-02-at-12.42.00-PM.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jah/c9c174db5a0b05b0f6e55c495a2a30fd/Screen-Shot-2018-08-02-at-12.42.00-PM.png)

Maintenant notre Soracom Air Device est capable de publier avec succès des messages depuis notre Raspberry Pi vers notre canal PubNub. Avec cette configuration, nous sommes prêts à écrire le code pour publier à partir du capteur ultrasonique et souscrire à partir de l'application mobile Android.

Publier - Capteur ultrasonique Script Python
--------------------------------------------

Nous allons écrire notre code python dans un script appelé **sensor\_publish.py** (ce script doit se trouver à l'intérieur du Raspberry Pi !). Commencez par importer certains des modules dont nous aurons besoin au début du script. Le module **RPI.GPIO** nous permettra d'obtenir des données des capteurs. Le module **time** nous permettra d'obtenir périodiquement des lectures du capteur. **Signal** et **sys** nous permettront d'écrire notre méthode qui tue le script et arrête de lire les données du capteur lorsque l'utilisateur utilise la commande ^C. **Subprocess** et **json** nous permettront d'analyser notre booléen dans le format JSON String approprié et de l'envoyer à notre [canal PubNub](https://www.pubnub.com/docs/general/channels/overview).

```js
import RPi.GPIO as GPIO
import time
import signal
import sys
import subprocess
import json
```

### Configuration du capteur

Après avoir importé nos modules, nous devons nous assurer que notre objet GPIO utilise les numéros de broches de la carte Raspberry Pi. Nous le ferons avec la ligne suivante.

```js
GPIO.setmode(GPIO.BCM)
```

Nous devons ensuite assigner des valeurs à nos broches d'entrée et de sortie. Notre broche d'entrée s'appelle **ECHO** et notre broche de sortie s'appelle **TRIG**. ECHO est connecté à la broche 18**(GPIO 24**) et TRIG est connecté à la broche 16**(GPIO 23**), comme vous pouvez le vérifier sur votre configuration Raspberry Pi. Nous devons également initialiser notre variable

```js
occupied
```

que nous utiliserons pour garder une trace de la dernière mise à jour de l'état de la place de parking. Nous l'initialiserons à False.

```js
TRIG = 23
ECHO = 24
occupied = False
```

Ensuite, nous définirons notre fonction qui configurera notre capteur. Nous nommerons cette fonction

```js
setup_sensor()
```

. Ici, nous devons définir quelle broche est notre entrée et quelle broche est notre sortie. Nous appellerons cette fonction plus tard dans notre fonction principale.

```js
def setup_sensor():
  GPIO.setup(TRIG, GPIO.OUT)
  GPIO.setup(ECHO, GPIO.IN)
```

### Obtenir la lecture de la distance du capteur

Nous utiliserons la fonction

```js
get_distance()
```

pour obtenir les données relatives à la distance entre un objet et notre capteur. Cette fonction calcule le temps que le signal d'impulsion a mis pour aller et revenir de l'objet. En utilisant ce temps, elle calculera la distance entre le capteur et l'objet.

```js
def get_distance():
  # set Trigger to HIGH
  GPIO.output(TRIG, True)
  # set Trigger after 0.01ms to LOW
  time.sleep(0.00001)
  GPIO.output(TRIG, False)
  startTime = time.time()
  stopTime = time.time()
  # save start time
  while 0 == GPIO.input(ECHO):
    startTime = time.time()
  # save time of arrival
  while 1 == GPIO.input(ECHO):
    stopTime = time.time()
  # time difference between start and arrival
  TimeElapsed = stopTime - startTime
  # multiply with the sonic speed (34300 cm/s)
  # and divide by 2, because there and back
  distance = (TimeElapsed * 34300) / 2
  return distance
```

### Publication de la disponibilité des places de parking

Nous publierons la disponibilité de notre place de parking dans la fonction principale de notre script python. C'est la fonction qui sera exécutée une fois le script lancé. La fonction principale doit effectuer les actions suivantes dans l'ordre.

1.  Mise en place du capteur
2.  Effectuer une première vérification de la disponibilité de la place de parking
3.  Vérifier si le statut a changé (toutes les 5 secondes) : S'il a changé, publier un message indiquant le nouvel état. Enregistrer ce statut comme le nouveau statut mis à jour en dernier lieu.

Pour configurer le capteur, nous appellerons la fonction que nous avons définie précédemment,

```js
setup_sensor()
```

. Ensuite, il effectuera une vérification initiale pour voir si la place de parking est disponible ou vacante. Nous définirons la méthode

```js
initial_check()
```

pour ce faire.

Nous aurons ensuite une boucle qui sera exécutée toutes les 5 secondes pour vérifier le nouveau relevé de distance de la voiture. Si la distance obtenue par la fonction

```js
get_distance()
```

est supérieure à 7 cm (la longueur de la place de parking dans mon modèle), nous pouvons en déduire que la place de parking est libre. Dans ce cas, la distance relevée par la fonction n'est que du bruit. Si elle est inférieure à 7 cm, nous savons que la place de parking est occupée par une voiture.

Afin de minimiser les dépenses et de maximiser l'efficacité, nous ne mettrons à jour l'état de la place de parking que si le capteur indique que l'état a changé depuis la dernière lecture. Ceci est illustré ci-dessous :

```js
if __name__ == '__main__':
  setup_sensor()
  initial_check()
  while True:
    if (occupied and (get_distance() >= 7)) or (not occupied and (get_distance() < 7)):
         // TODO toggle the availability of the parking space and publish new status
    time.sleep(5)
```

Notre fonction

```js
initial_check()
```

affectera notre variable

```js
occupied
```

à l'état actuel de la place de parking. Nous devons publier ceci en utilisant le module

```js
subprocess
```

que nous avons importé plus tôt. Ce module nous permet d'exécuter des commandes de terminal à partir d'un script python. En utilisant la méthode

```js
Popen()
```

nous passons simplement un tableau de chaînes de caractères à partir de la commande, comme vous le feriez dans un terminal. Après **\-m**, nous voulons passer le message encodé comme une chaîne JSON, avec la clé "occupied" et la valeur de la variable

```js
occupied
```

. Nous pouvons le faire en appelant notre méthode d'aide

```js
convertToJsonString()
```

qui prend un booléen et le convertit en un message JSON que nous pouvons envoyer.

```js
def initial_check():
  occupied = True if get_distance() < 7 else False
  subprocess.Popen(["mosquitto_pub", "-h", "beam.soracom.io", "-p", "1883", "-t", "parking_spot", "-m", convertToJsonString(occupied)], stdout=subprocess.PIPE)
  print(occupied)
```

```js
def convertToJsonString(occupied):
  dictionary_object = {
    "occupied": occupied
  }
  return json.dumps(dictionary_object)
```

Enfin, à l'intérieur de notre boucle qui est exécutée toutes les 5 secondes dans notre fonction principale, nous aurons le code suivant. Celui-ci fera basculer le booléen occupé et le publiera sur notre canal **parking\_spot****,** s'il est différent de son dernier statut mis à jour.

```js
occupied = not occupied
subprocess.Popen(["mosquitto_pub", "-h", "beam.soracom.io", "-p", "1883", "-t", "parking_spot", "-m", convertToJsonString(occupied)], stdout=subprocess.PIPE)
print(occupied)
```

### Script de mise à mort

Nous devons également nous assurer que notre script python peut être tué correctement. Nous définissons

```js
close()
```

comme la fonction qui est appelée lorsqu'un utilisateur tue le script avec la commande ^C. Ici, nous pouvons nettoyer nos relevés de capteurs avec la ligne

```js
GPIO.cleanup()
```

.

```js
def close(signal, frame):
  print("Turning off ultrasonic distance detection...")
  GPIO.cleanup()
  sys.exit(0)
signal.signal(signal.SIGINT, close)
```

Félicitations, nous avons maintenant écrit un script python qui publie des mises à jour de l'état de la place de parking.

S'abonner - Application mobile Android
--------------------------------------

Maintenant que notre capteur publie avec succès des données sur notre canal PubNub, nous devons configurer l'application mobile pour qu'elle soit abonnée au canal contenant les données sur la disponibilité des places de parking.

Nous devons d'abord ajouter les dépendances gradle suivantes dans le fichier build.gradle de notre module afin d'utiliser le [SDK PubNub Android.](https://www.pubnub.com/docs/sdks/android)

```js
implementation group: 'com.pubnub', name: 'pubnub-gson', version: '6.4.5'
```

Ensuite, nous ajouterons les autorisations suivantes dans le manifeste Android pour permettre à notre application d'utiliser Internet.

```js
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```

Pour cette application mobile, nous construirons une activité, la classe **MainActivity** , qui contiendra une vue de base composée de trois éléments d'interface utilisateur.

-   TextView pour indiquer la disponibilité
-   ImageView pour l'icône de la voiture
-   ImageView pour l'icône de la place de parking

Nous utiliserons le TextView pour indiquer si la place de parking est disponible et nous aurons une animation simple montrant l'icône de la voiture à l'intérieur ou à l'extérieur de la place de parking. La voiture garée aura une position Y de

```js
203f
```

et la voiture non garée aura une position Y de

```js
903f
```

. Afin de montrer si la place de parking est libre ou occupée, nous ferons basculer sa position entre les deux à l'aide d'une animation.

![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jai/c49db6142edb3aba23c185ba1cc254d4/Screenshot_20180802-125832.png "Smart Parking Lot") [![Smart Parking Lot](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jak/13634e1cfbae33fbc5da29409018fe87/Screenshot_20180802-125822.png "Smart Parking Lot")](https://images.ctfassets.net/3prze68gbwl1/asset-17suaysk1qa1jaj/ac205dec3aff8b815d037ebb91ac8e53/Screenshot_20180802-125822.png)

Tout d'abord, nous allons déclarer les champs de notre classe MainActivity.

```js
PubNub pubNub;
TextView occupiedText;
ImageView car, parkingSpot;
float outsideCar = 903f;
float parkedCar = 203f;
```

Ensuite, nous allons instancier les éléments de l'interface utilisateur avec la méthode

```js
findViewById()
```

à l'intérieur de la méthode

```js
onCreate()
```

de notre activité. Nous devons nous assurer que le **fichier de présentation de l'activité principale** contient les éléments d'interface utilisateur suivants, avec les identifiants appropriés, comme indiqué ci-dessous. Les identifiants que j'ai choisis sont

```js
occupiedText
```

,

```js
car
```

, et

```js
parkingspot
```

. Pour voir mon fichier de présentation complet, [cliquez ici](https://github.com/kaushikravikumar/Smart-Parking/blob/master/SmartParkingAndroid/app/src/main/res/layout/activity_main.xml).

```js
occupiedText = findViewById(R.id.occupiedText);
car = findViewById(R.id.car);
parkingSpot = findViewById(R.id.parkingspot);
```

Nous devons maintenant instancier notre instance

```js
PubNub
```

afin de pouvoir faire des appels à l'API PubNub depuis notre application Android. Pour ce faire, nous allons écrire le code suivant et passer la **Subscribe Key** et la **Publish Key** que nous avons générées lors de la création de l'application dans la [PubNub Admin Console](https://dashboard.pubnub.com/login).

```js
PNConfiguration pnConfiguration = new PNConfiguration();
pnConfiguration.setSubscribeKey("ENTER_SUBSCRIBE_KEY_HERE");
pnConfiguration.setPublishKey("ENTER_PUBLISH_KEY_HERE");
pnConfiguration.setSecure(true);
pubNub = new PubNub(pnConfiguration);
```

Maintenant que nous avons instancié notre instance

```js
PubNub
```

nous pouvons nous abonner au canal sur lequel notre capteur publie les données de disponibilité du parking, **parking\_spot**. Pour ce faire, nous allons devoir ajouter un callback listener pour lorsqu'un message a été publié sur le canal. Ensuite, nous devons nous abonner au canal. C'est ce que nous voyons ci-dessous.

```js
pubNub.addListener(new SubscribeCallback() {
      @Override
      public void status(PubNub pubnub, PNStatus status) {
      }
      @Override
      public void message(PubNub pubnub, PNMessageResult message) {
         // HANDLE MESSAGE
      }
      @Override
      public void presence(PubNub pubnub, PNPresenceEventResult presence) {
      }
  });
  pubNub.subscribe()
          .channels(Arrays.asList("parking_spot")) // subscribe to channels
          .execute();
```

Nous allons ensuite mettre en œuvre la logique de traitement du message. Nous voulons essentiellement faire basculer la disponibilité de la place de parking dans l'interface utilisateur de notre application mobile en vérifiant son état d'occupation actuel. Nous allons donc vérifier le message qui vient d'être publié sur notre canal pour voir si la place de parking est maintenant disponible ou occupée. Dans le cas où elle est disponible, nous appellerons notre méthode d'aide

```js
carLeaveAnimation()
```

. Dans le cas où elle est occupée, nous appellerons notre méthode d'aide

```js
carEnterAnimation()
```

. Ainsi, à l'intérieur de notre méthode

```js
message()
```

nous avons ce qui suit.

```js
final boolean occupied = message.getMessage().getAsJsonObject().get("occupied").getAsBoolean();
 runOnUiThread(new Runnable() {
     public void run() {
         if(occupied)
         {
             carEnterAnimation();
         }
         else
         {
             carLeaveAnimation();
         }
     }
 });
```

Dans

```js
carEnterAnimation()
```

nous définissons simplement la fenêtre de texte comme étant occupée. Nous appelons également la méthode

```js
animate()
```

sur la vue-image de la voiture et déplaçons sa position Y dans la place de parking (à la valeur de la coordonnée Y stockée dans la variable,

```js
parkedCar
```

). Dans

```js
carLeaveAnimation()
```

nous définissons simplement la vue textuelle comme étant disponible et appelons la méthode

```js
animate()
```

sur la vue-image de la voiture pour déplacer sa position Y à l'extérieur de la place de parking (à la valeur de la coordonnée Y,

```js
outsideCar
```

).

```js
private void carEnterAnimation()
{
    car.animate().y(parkedCar).setDuration(1500);
    occupiedText.setText("Occupied");
}
private void carLeaveAnimation()
{
    car.animate().y(outsideCar).setDuration(1500);
    occupiedText.setText("Vacant");
}
```

  
**Si le contenu intégré n'est pas disponible** sur cette page, il peut également être consulté à l'[adresse https://www.youtube.com/embed/KySPa\_D2ne0?enablejsapi=1&origin=https%3A%2F%2Fwww.pubnub.com](https://www.youtube.com/embed/KySPa_D2ne0?enablejsapi=1&origin=https%3A%2F%2Fwww.pubnub.com).

Voilà pour notre application mobile ! Elle reçoit maintenant avec succès des mises à jour du capteur sur la disponibilité de notre place de parking.

Lancement de l'application
--------------------------

Pour démarrer le capteur, entrez simplement dans le répertoire dans lequel se trouve votre script à partir du terminal du Raspberry Pi. Exécutez ensuite la commande suivante.

```js
python sensor_publish.py
```

Vous verrez que votre capteur a été mis en marche et qu'il vérifie les relevés de distance. Lancez l'application mobile Android et vous devriez voir que l'interface utilisateur de l'application mobile se met à jour et affiche le statut de la place de parking.

Conclusion
----------

Félicitations ! Nous avons maintenant construit une application [IoT](https://www.pubnub.com/solutions/iot-device-control/) simple de stationnement intelligent. **Pour le code source complet, [cliquez ici](https://github.com/PubNubDevelopers/Smart-Parking)**. En intégrant PubNub et Soracom, nous avons construit une application IoT qui utilise le LTE pour envoyer des messages en temps réel depuis le Raspberry Pi. Au lieu d'être limitée par un réseau wifi, notre application Smart Parking IoT est extrêmement portable et parfaite pour une utilisation en extérieur.

Consultez également notre [démo de tableau de bord IoT](https://www.pubnub.com/demos/iot-dashboard/) et notre [tutoriel IoT basé sur ce tableau de bord](https://www.pubnub.com/tutorials/iot-dashboard/).

Comment PubNub peut-il vous aider ?
===================================

Cet article a été publié à l'origine sur [PubNub.com](https://www.pubnub.com/blog/smart-parking-iot-simulation-with-realtime-space-monitoring/)

Notre plateforme aide les développeurs à construire, livrer et gérer l'interactivité en temps réel pour les applications web, les applications mobiles et les appareils IoT.

La base de notre plateforme est le réseau de messagerie périphérique en temps réel le plus grand et le plus évolutif de l'industrie. Avec plus de 15 points de présence dans le monde, 800 millions d'utilisateurs actifs mensuels et une fiabilité de 99,999 %, vous n'aurez jamais à vous soucier des pannes, des limites de concurrence ou des problèmes de latence causés par les pics de trafic.

Découvrez PubNub
----------------

Découvrez le [Live Tour](https://www.pubnub.com/tour/introduction/) pour comprendre les concepts essentiels de chaque application alimentée par PubNub en moins de 5 minutes.

S'installer
-----------

Créez un [compte PubNub](https://admin.pubnub.com/signup/) pour un accès immédiat et gratuit aux clés PubNub.

Commencer
---------

La [documentation PubNub](https://www.pubnub.com/docs) vous permettra de démarrer, quel que soit votre cas d'utilisation ou votre [SDK](https://www.pubnub.com/docs).