How to implement door unlocking system with Raspberry Pi, iPhone and service in cloud

Sławek Peszke
inFullMobile Blog
Published in
13 min readApr 18, 2018

Dear reader, I assume that you are interested in all tech news. One of the most interesting recent times are those that combine hardware and software — often classified as IoT (Internet of Things).

Observing the market, you could have noticed that the so-called Smart Home sector is gaining strength and serious players on the market are introducing more and more “smart” devices as well as offer more and more advanced systems integrating these devices to work in a homogeneous environment — some of them can work with integration platforms from Apple (Home Kit with assistant Siri), Google (Google Home with voice assistant), Amazon (Smart Home with Alex voice assistant) and Microsoft (along with Cortana voice assistant).
I suppose you, like me, like devices that make your everyday life easier and would gladly equip you with your home. However, it is not always possible due to the high price or they not always fully meet your expectations.

There is an alternative solution that can give you a lot of fun, new knowledge and finally a practical solution to the problem you may face on daily basis.
That’s how it was with me — I’m interested in IoT devices, I like programming and I wanted to learn more about the hardware-software combination and finally I needed to improve some daily activities — there was no other option — “smart” system needed to be built :)

The solution that I will describe has been created to facilitate one everyday activity: opening the gate to a multi-family building to its residents (including myself).

Perhaps you are wondering what’s the point!? Maybe you think that it would be a good idea to improve this activity, but there are already many products out there and there is no reason in duplicating them.
If you are interested in how I decided to solve this problem, let me take you through a typical scenario where a person enters a multi-family building:

Person holds the key to the gate scenario:

  1. Pulls out the key (e.g. from the pocket)
  2. Unlocks the lock with the key
  3. Person gets in

Person has access code to the intercom scenario:

  1. Types many numbers to unlock the lock (what if it’s unclear what’s the combination? :))
  2. Intercom unlocks the electrolock
  3. Person gets in

This is not an extremely complicated activity and it may not make sense to optimise it, but if you ever tried to enter the building with your hands holding shopping bags, or your key to the gate was tucked away and it took a long time to take it out, you would certainly be happy with the solution, which would allow you to have the door open to the building at the touch of a button! Without looking for a key, without pressing a long sequence on the numbers on intercom’s keypad — only the iPhone in your pocket and one button on the door and you are in!

So, lets do it!

In order to achieve the intended goal, we will need a solution that will automatically recognise our presence near by the entrance gate and after pressing the button on the door, the system will verify our permissions, and then (if we are allowed to pass the door) open the electrolock and thus release the door. Sounds simple, right?

The architecture of our system will be as simple as possible — I want to share with you a solution that is easy to implement and at the same time with the potential for further development according to your extra needs.

Most of the door lock control systems for buildings work in the sequence:

System listens to the presence of a person  Person near by the door (with smartphone)  System detects presence  Person launches the application  Person unlocks the door via the app  System verifies permissions  System unlocks the door

Our solution:

System listens to the presence of a person → Person near by the door (with iPhone) → System detects presence → Person presses the gate opening button on the door → System verifies the permissions → System unlocks the door

Please, notice how comfortable it is. No waisting time for getting the phone, launching the app and interacting with the app to open the door.
It’s as simple as one button click.

How safe is our solution?

Please, keep in mind that the level of security against unauthorized use does not have to be very high here — the purpose is to prevent people who should not cross the building’s gate, but it won’t be a barrier for a person who previously possesses an iPhone with granted access to the gate. That’s why our solution is suitable for managing access to a building, but it should not be used to control access to housing.
Here, we focus on convenience of use with a reasonable level of security.

Prerequisites:

  • The gate to the building with an electric lock (with access to a key and / or intercom)
  • Internet access for the gateway controller (e.g. WiFi in range)
  • A computer with macOS operating system

Parts of our system:

  • Gate controller (Raspberry Pi)
  • User’s smartphone (iPhone)
  • Cloud service (backend application deployed on Heroku)

Used communication channels within the system:

  • HTTPS
  • Bluetooth Low Energy (BLE 4.0)

The diagram below shows the principle of the entire system. It will allow you to familiarise yourself in detail with the role of each piece of the system, as well as with the interactions between them.

What do we need to assemble our IoT solution?

Collect the following items:

  • Raspberry Pi Zero W microcomputer (I’ll use also short name: “RPi”)
    Thanks to this device, we will have, apart from an advanced controller with the linux OS, also a WiFi and BLE 4 module, without the need to attach additional modules
  • microSD card (at least 16GB) with adapter for SD card reader
  • iPhone 5 or newer with iOS 10.3 (or newer)
  • Power supply with micro USB connector to drive the Raspberry Pi
  • Breadboard
  • 2 LED diodes (green and red)
  • Relay module (e.g. SRD-05VDC-SL-C)
  • Push button
  • Resistors: 2 × 300Ω and 1 × 10kΩ
  • Wires

How to connect all elements with each other?

Here is the recipe:

Note: Please, take into account that the relay module you have chosen may differ from the one on diagram above, so connect according to specification.

This is how my physical implementation of the above scheme looks like:

As we already know what and how to connect with each other, it is time to prepare individual components of the system.

Configuration time

As first we will prepare a gateway controller — Raspberry Pi together with subassemblies.

To “be alive”, Raspberry Pi needs operating system, and in our case it will be Raspbian Stretch Light. How to equip RPi with OS? Description may be found here: Raspberry Pi Zero Headless Setup.

Once we have Raspberry Pi prepared and connected to the WiFi network (yes, thats important 😃), we can take care of preparing the environment for our program, which will be responsible for several key things:

  • communication with iPhone (via BLE 4.0)
  • generating a token and sending it to the service in the cloud (via HTTPS)
  • validation of the token transferred from the iPhone
  • opening the electrolock of the main gate

To handle the above I’ve prepared a program written in JavaScript that will be run within the Node.js environment. Later on, I will explain the more important parts of the code, but now we will continue the configuration thus we still have a few things to be installed.

Node.js installation

Log in to RPi via SSH (as user pi) and execute the following commands:

$ sudo apt-get update

$ sudo apt-get dist-upgrade

$ curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -

$ sudo apt-get install -y nodejs

The above sequence guarantees the latest versions of the packages, and then we install the latest version of Node.js.

To check whether the operation was successful and what Node.js version we have, run the command:

$ node --version

The next step is to install the Node.js libraries that are used in the application and these are:

  • UUID generator — generates authorization token
    $ npm install uuid
  • Cache — stores generated tokens
    $ npm install node-cache
  • Console Log Formatter — makes log messages more developer friendly
    $ npm install console-stamp
  • GPIO Pins Controller — lets us read and write signals from/to RPi board pins
    $ npm install rpi-gpio
  • Bluetooth Low Energy — handles all BLE communication
    Due to the fact that the installation is a bit more complicated, please follow the instruction given here
  • GPIO Button Event Emitter — handles buttons’ events
    $ npm install rpi-gpio-buttons
  • Request — supports HTTPS operations
    $ npm install request

Now we can install our program on RPi.

To do this, log in to RPi via SSH and create a folder:

$ mkdir /home/pi/gateguard

Download the ZIP-ed source code from GitHub and unpack it, and then move *.js files to the newly created folder:

$ wget -O gateguard-rpi.zip https://github.com/inFullMobile/gateguard-rpi/archive/master.zip

$ unzip gateguard-rpi.zip

$ cp -r gateguard-rpi-master/* /home/pi/gateguard/

We still have one more thing to configure, but we can’t do it until the app in the cloud is setup — it is about a generated URL address of our application, which will be included in the code on PRi, so that RPi can connect to it in the cloud.

Raspberry Pi is almost ready… so it’s time to launch another element of our system — a service in the cloud, which will be responsible for coordinating communication between the iPhone and RPi.

Two more elements of the system require an Xcode environment (preferably the newest one, currently Xcode 9.3) and if you do not have it yet, please install it from the Apple AppStore store (https://itunes.apple.com/pl/app/xcode/id497799835?mt = 12), then launch and complete the installation.

The cloud app will be deployed on the Heroku platform, where we can host our application for free for development and education purposes.

As the first step, I suggest setting up an account on the Heroku platform, within which our application will be deployed and maintained.
Go to heroku.com and create an account (if you do not have one already).

Then we will need the Heroku Command Line Interface (aka Heroku CLI) installed on the computer. We’ll use it to deploy the application.
To install Heroku CLI, follow the instruction: Heroku CLI Installation.

As the application is written in Vapor framework (Swift on board 😆), please install Vapor Tool Box which will support the app: Vaport Tool Box Installation.

In the next step, download the application code from the repository. To do this efficiently, use the Git client:

$ git clone https://github.com/inFullMobile/gateguard-cloud.git

Let’s prepare our project for deployment with Heroku CLI commands:

$ cd gateguardcloud

$ rm -rf .git #it removes current git version control files

$ heroku login #once asked, provide your username (email) and password

#create new git local repository$ git init$ git add .$ git commit -m “Initial commit”

We can now deploy our application to Heroku servers:

$ vapor heroku init

as a result you will be asked some questions and you may answer like I did:

Would you like to provide a custom Heroku app name?y/n> nWould you like to deploy to a region other than the US?y/n> yRegion code (us/eu):> euhttps://pacific-lowlands-45092.herokuapp.com/ | https://git.heroku.com/pacific-lowlands-45092.gitWould you like to provide a custom Heroku buildpack?y/n> nSetting buildpack...Are you using a custom Executable name?y/n> nSetting procfile...Committing procfile...Would you like to push to Heroku now?y/n> yThis may take a while...Building on Heroku ... ~5-10 minutes [  •                      ]

and finally

Building on Heroku ... ~5-10 minutes [Done]Spinning up dynos [Done]Visit https://dashboard.heroku.com/apps/App is live on Heroku, visithttps://pacific-lowlands-45092.herokuapp.com/ | https://git.heroku.com/pacific-lowlands-45092.git

Remember generated domain for your cloud app for later use (in my case it is https://pacific-lowlands-45092.herokuapp.com)

It is a good moment to return to the code on RPi and configure the correct URL address of our service in the cloud. To do this, reconnect to RPi via SSH and open the file /home/pi/gateguard/cloud_module.js for editing then enter correct address of the service on Heroku (code: line 35), where in my case it look like this:

uri: ‘https://pacific-lowlands-45092.herokuapp.com/register-token',

We need two more unique identifiers for Bluetooth communication, and you can get them by doing a 2× command:

$ uuidgen

In my case, it has been generated UUIDs:

  • 93384AB6–9EB1–4AF2–90FB-F88ABB6F79AF
  • 4E98BE1C-F8D9–46AD-9D08-C0AAA7DFEE7A

The first on them will be used on Raspberry Pi as BLE peripheral’s service identifier, the second will be assigned to the peripheral’s characteristic.

Assign your generated UUIDs to service and characteristics in source file /home/pi/gateguard/shared_module.js respectively:

this.bleServiceUUID = '93384AB6-9EB1-4AF2-90FB-F88ABB6F79AF'
this.bleCharacteristicUUID = '4E98BE1C-F8D9-46AD-9D08-C0AAA7DFEE7A'

Are you ready to launch the program on PRi? 10… 9… 8…

$ nohup sudo node /home/pi/gateguard/gateguard.js > /home/pi/gateguard/gateguard.log &

where the nohup command will guarantee the work of the program in the background as we disconnect from the RPi, while sudo is necessary for our program to work on permissions allowing the it to access BLE and IO ports of our microcomputer. All logs thrown by our program will go to gateguard.log file.

Time for the second element of the system — an application for the iPhone.

In this case you just need to download the project source files from the repository:

$ git clone https://github.com/inFullMobile/gateguard-ios.git

and open the project in Xcode.
Before running on the iPhone, set the correct URL address of the app in cloud, what can be done in project’s source file HttpClient.swift — change the address assigned to the constant:

// That's my URL address! Use yours ;)
static let gateGuardHost = URL(string: "https://pacific-lowlands-45092.herokuapp.com")!

Now configure the correct UUIDs for BLE service and characteristic in the BLEService.swift file (remember to assign appropriate UUIDs to service and characteristics — the same as in sources of PRi app):

static var serviceUUID: CBUUID {return CBUUID(string: "93384AB6-9EB1-4AF2-90FB-F88ABB6F79AF")}static var newTokenNotificationCharacteristicUUID: CBUUID {return CBUUID(string: "4E98BE1C-F8D9-46AD-9D08-C0AAA7DFEE7A")}

Ensure that Bluetooth on iPhone is ON!

Now you can launch the application on your phone.

Congratulations! You did it! Our GateGuard should now work as expected — test it with alternately Bluetooth switched ON and OFF on the phone, and you will observe the result of the action in the form of flashing or glowing LEDs and the operation of the relay, which connected to the electrolock will unlock the gate to the building.

For your information, I’ll explain the LEDs behaviour:

  • The green LED blinks — the gate opening button has been pressed, the iPhone with the Gate Guard application is within RPi BLE range and the authorization is in progress
  • The green LED is on — the door’s electrolock is open
  • The red LED blinks — the gate opening button has been pressed but RPi has not identified the iPhone with the Gate Guard application running
  • The red LED is on — user hasn’t passed the authorization successfully (the token from the iPhone is invalid) and the gate will not be opened

Please note that there is no authentication step in the iPhone’s application. Due to the simplicity of the solution, I’ve skipped the authentication process, but there is nothing to prevent you from adding a login screen that will protect the application from unauthorized use 😏.

If you were curious how it worked for me, fortunately I have recorded it 😃

System granted access to the gate
System didn’t grant access to the gate

A bit about code itself

If you are interested in how communication between RPi, iPhone and application in the cloud has been resolved, stay with me, and I will explain the most important pieces of the code right now.

If you are new in BLE subject, I recommend very good introduction made by Mikołaj Chmielewski in the article Introduction to Bluetooth LE on iOS: Mi Band 2 Case Study.

What’s happening on Raspberry Pi?

Our device is responsible for the following:

  • acting as a BLE peripheral for iPhone connected to it
  • generating a new token
  • transferring token to the cloud app
  • validation of a token transferred from the iPhone
  • electrolock control

Let’s go through the source code to see what’s happening there.

Following the above bullet points, acting as a BLE peripheral for iPhone connected to it is handled by the code:

Generation of authorization token is done by the code:

UUID generated with use of node.js uuid lib

Transferring token to the cloud app is realised this way:

HTTPS operations with node.js request lib

Another step is validation of the token:

Electrolock controlling is implemented in relay_module.js.

Opening the gate is happening here:

What about iPhone’s role?

The app mainly works in background and

  • is looking instantly for particular UUID which represents RPi service/characteristic
  • gets requested token (request comes from RPi) from cloud service
  • sends token back to RPi for further authorization procedure

Instant looking around for familiar Raspberry Pi looks like this:

and successively

Once the peripheral device is connected and gate’s button pressed, it generates new authorization token (unknown for iPhone’s app) and requests for it. Token is sent to RPi app right after being taken from cloud service.

There is also token exchange platform — service in cloud.

Backend application written in Swift with use of Vapor framework and hosted on Heroku servers. Simple service which is responsible for two things:

  • storing newly generated authorization token (for a limited time only)
  • answering with token while being asked for it with tokenID

First responsibility is handle this way:

Another is implemented that way:

As you can see, all pieces of the system talk to each other via BLE and HTTPS. Details of implementation you can always find in provided repositories.

That was huge fun for me to build that system and I hope you may find it interesting too.

Sławek Peszke is an iOS developer at inFullMobile, an international digital product design and development studio based in Warsaw, Poland.

Fell free to contact us: hello@infullmobile.com

--

--