Intelligent Parking System with Live Space Tracking
Published: 2024-01-11 11:59:20

Never before have we lived in an era, where every “thing” could seamlessly be interconnected by the Internet. The idea of [Internet of Things (IoT)](https://www.pubnub.com/solutions/iot-device-control/) has continually transformed our world by presenting innovative solutions to numerous problems using an **Event Driven Pub/Sub Architecture**. For example, to solve the exhausting problem of finding parking in crowded spaces, parking garages have installed live electronic dashboards showing which spots are available by subscribing to status updates published from individual sensors in a parking lot. Building such an IoT app can be challenging due to a number of hurdles.

One of these hurdles is hosting a server capable of handling messages sent between the mobile app and the sensor devices in real time. Another is hosting a wifi network capable of supporting every single embedded sensor device in the smart parking lot.

By using **PubNub** and **Soracom** alongside each other, however, developers can quickly circumvent these challenges. With PubNub’s real-time platform, developers can easily [build complex IoT solutions](https://www.pubnub.com/solutions/iot-device-control/) for [vehicle monitoring](https://www.pubnub.com/solutions/transport-delivery/) without worrying about tedious tasks such as hosting servers. Additionally, with [Soracom Air](https://www.soracom.io/products/air/) and [Soracom Beam](https://www.soracom.io/products/beam/), developers can easily build IoT solutions that utilize LTE, instead of a restrictive WFI network.

Tutorial Overview
-----------------

In this tutorial, we will build a Smart Parking Simulation using Raspberry Pi and an ultrasonic sensor to detect whether a parking spot is occupied or vacant. We will use Soracom Air to send messages from the sensor to PubNub via cellular data. Then using PubNub’s Publish-Subscribe API, we will make live parking data instantly available to all the app’s mobile users. This is shown in the following diagram.

* * *

**For the full source code, [click here](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)

To build this demo, you will need:

1.  Raspberry Pi (Any Version)
2.  Breadboard
3.  HC-SR04 Ultrasonic Sensor
4.  1 Female-female + 6 male-female jumper wires
5.  1 **1k Ω** resistor and 1 **2k Ω** resistor
6.  MicroSD card + MicroSD to SD Adapter
7.  Huawei USB Stick Modem
8.  Soracom Air Sim Card

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

### **1\. Raspbian OS Installation**

If you haven’t already, make sure to install the Raspbian OS onto your Raspberry Pi. To do this, we will first install it locally on our computer. This will be of disk image format, so we will need to flash the disk before using it. You can use [Etcher](https://www.balena.io/etcher/) to flash the disk onto your microSD card 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)

Once the Raspbian OS files are on our microSD card Adapter, we may remove the microSD card from the adapter and then insert it into the bottom slot of our Raspberry Pi. With the OS installed, you may now boot up the Raspberry Pi by plugging in a keyboard, mouse, monitor, and power source.

### 2\. Configure Sensor

[![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.  Plug 3 of our **male-female jumper wires** into the **HC-SR04 ultrasonic sensor** in the **VCC, Echo, and GND slots.** Plug one of our **female-female jumper wires** into the **Trig** slot of the sensor.
2.  Plug the **VCC** **wire** into the **positive rail** of our breadboard and the **GND** **wire** into the **negative rail**.
3.  Plug **GPIO 5V** on the Raspberry Pi to the **positive rail** of our breadboard and **GPIO GND** to the **negative rail**.
4.   Plug the **Trig wire** into **GPIO 23**.
5.  Plug the **Echo wire** into a **blank rail** on the breadboard.
6.  Link another blank rail using a **1k Ω resistor**. (The reason, we need resistors is so we can lower the voltage output to ensure that our Raspberry Pi is not damaged by the sensor configuration)
7.  Then link a blank rail using a **2k Ω resistor** to the negative rail of our breadboard leaving a space. If you do not have a 2k Ω resistor, you could create a series of 2 1k Ω resistors, as shown in the following picture.  [![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.  In the space we have left, we will use a **male-female jumper wire** to link to **GPIO 24**.

Congrats, we have now completed the configuration of our ultrasonic sensor. If you find yourself stuck with the configuration of the sensor, check out this [tutorial](https://thepihut.com/blogs/raspberry-pi-tutorials/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi) for a more detailed explanation. While you are building your circuit, remember that on the [breadboard’s](https://en.wikipedia.org/wiki/Breadboard) blank rails current flows horizontally and on the breadboard’s positive and negative rails, current flows vertically. Next, we will set up PubNub and Soracom into our IoT app.

PubNub Setup
------------

First, we will create our app in the [PubNub Admin Console](https://dashboard.pubnub.com/login) (**It’s free**). After creating the app in the console, you will see the publish and subscribe keys which we will use in the next step to connect PubNub and Soracom.

Soracom Setup
-------------

### **Register SIM**

We will head on over to the [Soracom Admin Console](https://console.soracom.io/). Here we will click **Register SIM** and input the **ICCID** and **PUK** digits, which you can find on the back of your **Soracom Air Sim Card**.

[![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)

### USB Modem Configuration

After registering our SIM card, we will remove the SIM chip (shown with the purple circle I’ve drawn around it in the image above). Then we will insert it into **Huawei USB Stick Modem**. Make sure that you have slid the SIM card all the way in, the right way facing up.

[![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)

In order to have our Raspberry Pi running on cellular data, we will simply plug the [Huawei USB Stick Modem](https://consumer.huawei.com/en/routers/e3372/specs/) into the USB port of the Raspberry Pi. A **solid blue light** (not blinking) shows that the modem is successfully picking up 3g data. If it is blinking it means it is still attempting to connect.

[![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)

Once, we have a solid blue light, we must add our USB Stick Modem to the Raspberry Pi’s Network Manager. To do this first install the Network Manager onto the Raspberry Pi. In your Raspberry Pi’s terminal type the following.

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

Then to connect our USB Stick Modem to our Soracom Account we must type the following command from our Raspberry Pi terminal. Substitute **<ENTER\_USERNAME>** and **<ENTER\_PASSWORD>** with your respective account credentials.

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

To make this configuration go into effect, we must reboot our Raspberry Pi.

```js
sudo reboot
```

Now to ensure that your USB Modem is being recognized by your Raspberry Pi’s Network Manager type in:

```js
ifconfig
```

You should see a 

```js
ppp0
```

 (your USB Modem) show up. Then type the following 3 terminal commands to ensure that you’ve downloaded Soracom’s ppp route metric script and that the script is run every time the USB modem is plugged in or restarted.

```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
```

Now, our USB Stick modem should be properly configured. If you’re still stuck on configuring the USB Stick Modem, make sure you read thoroughly over these [Soracom docs](https://github.com/soracom/handson/wiki/1.3.-USB-Dongle-configuration-tutorial-(SIM-pre-registered)).

### MQTT Setup

[**MQTT**](https://www.pubnub.com/guides/mqtt/) (Mosquitto) is the name of the protocol we will use in order to publish messages to our PubNub channel from the Raspberry Pi IoT App. In the Admin Console, we will open up the side navigation bar link titled Groups to **add a new Group**. We will call this new group, **Beam-Soracom**. Under basic settings for this new group, click on **Soracom Beam**. Here, we will create a **MQTT Entry Point**. Ensure that you have the following inputted when creating the [MQTT](https://www.pubnub.com/blog/what-is-mqtt-use-cases/) Entry Point. You will need to specify the Destination Type as **PubNub**. Where you see **Credentials Set**, we will add our [PubNub](https://admin.pubnub.com/#/register) credentials (**Publish and Subscribe Key**) to allow our Soracom device to publish messages to our PubNub channel.

[![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)

Then, we will select our Registered SIM card in the Admin Console and set its group to the one we just created, called **Beam-Soracom**. Ensure that you have clicked **activate** on our Registered SIM card, so that it is active and picking up data.

Now, we must install **mosquitto-clients** package onto our Raspberry Pi, so that we are able to use MQTT’s publish method. In the Raspberry Pi’s terminal run the following command.

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

With mosquitto-clients installed, we may test our **mosquitto\_pub** command, which we will use to publish a message to our PubNub channel. The format of our mosquitto\_pub command will be as follows. After **\-t** we will insert our channel name, **parking\_spot**. And after **\-m** we will insert a test message “test”. Pull up your Debug View on the PubNub Admin Console. Once you run the command below on the Raspberry Pi’s terminal, you should see that the message has successfully been published to our PubNub channel.

```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)

Now our Soracom Air Device is able to successfully publish messages from our Raspberry Pi to our PubNub channel. With this set up, we are ready to start writing the code to publish from the ultrasonic sensor and subscribe from the Android mobile app.

Publish – Ultrasonic Sensor Python Script
-----------------------------------------

We will write our python code in a script called **sensor\_publish.py** (this script must be inside the Raspberry Pi!). Begin by importing some of the modules we’ll need at the top of the script. The **RPI.GPIO** module will allow us to obtain data from the sensors. The **time** module will allow us to periodically obtain readings from the sensor. **Signal** and **sys** will allow us to write our method that kills the script and stops reading the sensor data when the user uses the command ^C.  **Subprocess** and **json** will allow us to parse our boolean into the appropriate JSON String format and send it to our [PubNub channel](https://www.pubnub.com/docs/general/channels/overview).

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

### Sensor Setup

After importing our modules, we must ensure that our GPIO object is using Raspberry Pi Board Pin Numbers. We will do this with the following line.

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

We must then assign values to our input and output pins. Our input pin is called **ECHO** and our output pin is called **TRIG**. ECHO is connected to pin 18 (**GPIO 24**) and TRIG is connected to pin 16 (**GPIO 23**), as you can verify on your Raspberry Pi setup. Also we must initialize our 

```js
occupied
```

variable which we will use to keep track of the last updated status of the parking spot. We will initialize it to False.

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

Next, we will define our function that will set up our sensor. We’ll name this function 

```js
setup_sensor()
```

. Here we must define which pin is our input and which is our output. We will call this function later in our main function.

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

### Obtain Sensor Distance Reading

We will use the function 

```js
get_distance()
```

 to obtain the data of how far an object is from our sensor. This function will perform a calculation on how long the pulse signal took to go and come back from the object. Using the time it took, it will compute the distance from the sensor to the object.

```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
```

### Publishing Parking Space Availability

We will be publishing our parking space’s availability in the main function of our python script. This will be the function that is executed once the script is started. The main function must do the following actions in order.

1.  Set up the sensor
2.  Perform an initial check on the availability of the parking space
3.  Check to see if status has changed (every 5 seconds): If it has changed then publish message of new status. Store this status as the new last updated status.

To set up the sensor we will call the function we defined earlier,

```js
setup_sensor()
```

. Next it will do an initial check to see if the parking space is available or vacant. We will define method 

```js
initial_check()
```

to do this.

We will then have a loop that is executed every 5 seconds to check the new distance reading of the car. If the distance reading obtained by function 

```js
get_distance()
```

 is greater than 7cm (the length of the parking space in my model), then we can infer that the parking space is vacant. The distance it is picking up is simply noise in this case. If it is less than 7cm, then we know that the parking space is being occupied by a car.

In order to minimize expenses and maximize efficiency, we will only update the status of the parking space if the sensor shows that the status has changed since the last reading. This is shown below:

```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)
```

Our 

```js
initial_check()
```

function will assign our variable 

```js
occupied
```

 to the current status of the parking space. We must publish this using the 

```js
subprocess
```

module we imported earlier. With this module, we are able to run terminal commands from a python script. Using the method 

```js
Popen()
```

, we simply pass an array of strings from the command as you would type it in a terminal. After **\-m**, we want to pass the message encoded as a JSON String, with key “occupied” and value the variable

```js
occupied
```

. We can do this by calling our helper method 

```js
convertToJsonString()
```

 which takes a boolean and converts it into a JSON string message that we can send.

```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)
```

Finally, inside our loop that is executed every 5 seconds in our main function, we will have the following code. This will toggle the occupied boolean and then publish it to our **parking\_spot** channel**,** if it is different from its last updated status.

```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)
```

### Kill Script

We must also ensure that our python script can be killed properly. We define 

```js
close()
```

 as the function that’s called when a user kills the script with the command ^C. In here, we can clean up our sensor readings with the line

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

.

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

Congrats, we have now written a python script that publishes updates of the parking space’s status.

Subscribe – Android Mobile App
------------------------------

Now that our sensor is successfully publishing data to our PubNub channel, we must set up the mobile app so it is subscribed to the channel containing parking spot availability data.

We must first add the following gradle dependencies into our Module build.gradle file in order to utilize the [PubNub Android SDK.](https://www.pubnub.com/docs/sdks/android)

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

Next, we will add the following Android Manifest Permissions to allow our app to use the internet.

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

For this mobile app, we will build one Activity, the **MainActivity** class. This Activity will contain a basic view consisting of 3 UI-Elements.

-   TextView for stating availability
-   ImageView for car icon
-   ImageView for parking space icon

We will use the TextView to state whether the parking space is available and we will have a simple animation showing the car icon inside of the parking space or outside of it. The parked car will have a Y position of 

```js
203f
```

and the not parked car will have a Y position of

```js
903f
```

. In order to show whether the parking spot is vacant or occupied we will toggle its position between the two using an 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)

First, we’ll declare the fields of our MainActivity class.

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

Then, we will instantiate the UI elements with the method 

```js
findViewById()
```

 inside our activity’s 

```js
onCreate()
```

method. We must ensure that the **Main Activity layout file** has the following UI elements included with the appropriate ID’s as specified below. The Id’s I’ve chosen are

```js
occupiedText
```

,

```js
car
```

, and

```js
parkingspot
```

. To see my complete layout file, [click here.](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);
```

Now we must instantiate our 

```js
PubNub
```

instance, so we can make calls to the PubNub API from within our Android App. In order to do this, we will write the following code and pass the **Subscribe Key** and **Publish Key** that we generated when creating the app in the [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);
```

Now, that we have instantiated our 

```js
PubNub
```

instance, we can subscribe to the channel our sensor is publishing parking availability data to, **parking\_spot**. In order to do this, we will need to add a callback listener for when a message has been published to the channel. Then we must actually subscribe to the channel. This is shown below.

```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();
```

We will then implement the logic of handling the message. We want to essentially toggle the availability of the parking spot in our mobile app UI by checking its current status of occupancy. Thus, we will check the message just published to our channel to see if the parking spot is now available or occupied. In the case that it is available, we will call our helper method 

```js
carLeaveAnimation()
```

. In the case that it is occupied, we will call our helper method 

```js
carEnterAnimation()
```

. Thus inside our 

```js
message()
```

method we have the following.

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

In 

```js
carEnterAnimation()
```

, we simply set the textview to say occupied. We also call the 

```js
animate()
```

method on the car’s imageview and move its Y position into the parking space (to the Y-coordinate value stored in variable, 

```js
parkedCar
```

). In

```js
carLeaveAnimation()
```

, we simply set the textview to say available and call the 

```js
animate()
```

method on the car’s imageview to move its Y position outside the parking space (to the Y-coordinate value,

```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");
}
```

  
**If the embedded content is not available** on this page, it can also be viewed at [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)

That’s it for our mobile app! Now it successfully receives updates from the sensor on the availability of our parking spot.

Running App
-----------

To start the sensor, simply enter the directory in which your script is located from the Raspberry Pi terminal. Then execute the following command.

```js
python sensor_publish.py
```

You will see that your sensor has now been turned on and is checking the distance readings. Run the Android mobile app and you should see that the mobile app’s UI will update and display the status of the parking spot.

Conclusion
----------

Congrats! We have now built a simple Smart Parking [IoT](https://www.pubnub.com/solutions/iot-device-control/) app. **For the full source code, [click here](https://github.com/PubNubDevelopers/Smart-Parking)**. By integrating PubNub and Soracom, we have built an IoT app that uses LTE to send real-time messages from the Raspberry Pi. Instead of being restricted by a wifi network, our Smart Parking IoT app is extremely portable and perfect for use outdoors.

Please also check out our [IoT Dashboard demo](https://www.pubnub.com/demos/iot-dashboard/) and [IoT Tutorial based on that dashboard](https://www.pubnub.com/tutorials/iot-dashboard/)

How can PubNub help you?
========================

This article was originally published on [PubNub.com](https://www.pubnub.com/blog/smart-parking-iot-simulation-with-realtime-space-monitoring/)

Our platform helps developers build, deliver, and manage real-time interactivity for web apps, mobile apps, and IoT devices.

The foundation of our platform is the industry's largest and most scalable real-time edge messaging network. With over 15 points-of-presence worldwide supporting 800 million monthly active users, and 99.999% reliability, you'll never have to worry about outages, concurrency limits, or any latency issues caused by traffic spikes.

Experience PubNub
-----------------

Check out [Live Tour](https://www.pubnub.com/tour/introduction/) to understand the essential concepts behind every PubNub-powered app in less than 5 minutes

Get Setup
---------

Sign up for a [PubNub account](https://admin.pubnub.com/signup/) for immediate access to PubNub keys for free

Get Started
-----------

The [PubNub docs](https://www.pubnub.com/docs) will get you up and running, regardless of your use case or [SDK](https://www.pubnub.com/docs)