Bluetooth Contact Tracing as a Service (Technical Implementation with Sample Code)

Agmo Studio is engaged as a partner to build Bluetooth Contact Tracing module for an official COVID-19 app of a South East Asia country on CSR basis. Before this, we have been doing couple of Bluetooth Low Energy (or known as Bluetooth Smart), like integration with iBeacon for indoor positioning purpose and connecting to Smart Health BLE Peripheral to read/write to the service’s characteristics.

TraceTogether Image Credit:

As we know, Singapore Govtech has launched first-of-its-kind and super novelty TraceTogether using Bluetooth Decentralized Network (Read more here). The are couple of good articles to discuss about the privacy protection implementation and how secure is the application in Medium: Article 1, Article 2 and Article 3. There’s also an official article about the myths busting fact. From the BlueTrace official website, the team will open source what they have built, and they are working around the clock to finalize it. (Last updated at 22 March 2020) From this interview article with the team, GovTech has a team of 40 professionals, spent 8 weeks and more than 10,000 hours to complete the development.

Our team was anxiously waiting for the open source, but we think we can’t wait further to help the government to trace the closed contacts of COVID-19 confirmed patients. Our team has been working day and night to implement Agmo’s version of TraceTogether using Bluetooth Smart in the past 2 weeks. Today, we will share about the preliminary implementation to help anyone who is building the same thing. We want to give credits to all authors of the articles in paragraph above, as it gives us a better clarity and saving us time for part of the reverse engineering process.

Before we start, it’s important to understand how BLE actually works. Each of your BLE devices have unique Service and Characteristic UUID. They are registered here: Service UUID and Characteristic UUID. However, for our implementation, we can just use a UUID which doesn’t crash with any of the pre-registered one to avoid conflict.

Image Credit –

First thing, we have built a Central Manager to try connecting to TraceTogether Service and read the encrypted payload from the UUID, it is working as expected. We know we are at the right path on the implementation, as we can get the same 160 byes as per described here.

The implementation shall contain a backend, Native iOS App and Native Android App (Supposed you can use Xamarin, React Native or other cross platform frameworks as well with native bridge). Here’s basically a checklist of components that you need to build:

Sender part:

– Create Bluetooth Peripheral Manager, to act as a sender for turning the users’ mobile phone as a beacon that broadcasts own identity 

– First, you need to configure your Service and Characteristic UUID, so that it’s unique for the receiver to recognise

– Second, you need to get the temporary ID from the backend, it’s recommended to refresh it on scheduled interval, say every 1 hour

Sample timestamp interval from TraceTogerher app. Image Credit:

– Third, you need to encrypt the payload with AES-256. The payload shall consist of temporaryId, phoneModel (iPhone X, Samsung Galaxy S8…)

– Then you can start to advertise with the defined UUID and encrypted payload using Peripheral Manager

Sample code to start advertising (library credit:

If the implementation is done correctly, you can use any BLE Probe Tool, like BlueCap or LightBlue in iOS and nRF Connect in Android to check if you can find the advertising devices, connect to it and read the characteristic. Look at AgmoTrace below.

Receiver part:

– Create Bluetooth Central Manager, to act as a receiver to scan for nearby users’ identity with the defined service UUID

Sample code to start scanning (library credit:

– Then, you loop through the devices, and connect one by one

– After connecting, you can start to read the encrypted payload

– Decrypt the payload with AES-256, you will get the contact’s temporaryId and phone model, then get other information along the scanning (RSSI, txPower – which can tell roughly how close is this contact in terms of physical distance)

– Create a local store (like using SQLite, Android Room, iOS CoreData, and insert each record which consists of:

i. TemporaryId (Obtained from decrypted payload)

ii. ModelPeripheral (Obtained from decrypted payload)

iii. ModelCentral (Central Manager’s device model)

iv. RSSI

v. TxPower

Sample SQLite Data From TraceTogether app. Image credit:

Backend part to create 2 APIs: (apart from user registration and bla bla)

– GetTemporaryId API 

Purpose: To get encrypted key to represent own identit

Input: Unique identifier which is verified and useful to contact (for instance: phone number, IC number if you have e-KYC)

Logic: Encrypt it with a private key that is stored in cloud

Output: TemporaryId

– UploadRecords API 

Purpose: To upload own records to the cloud, it will share the contacts that you are closed to (in term of physical distance)

Input: User’s identity and array of records


Even MCO is finished, we think the COVID-19 outbreak is still risky. Thus, it’s important for large scale corporates, app owners with high users volume and government to build the Contact Tracing in their current mobile applications to maximize the efficiency and coverage together.

We are offering Contact Tracing As A Service to any mobile applications to plugin.

For instance:

  1. If Grab has this contact tracing module, if a Grab Driver is confirmed patient (touch wood sorry), then we can easily identify all passengers involved (not only the user doing the booking, as this can already be identified by the current system) It saves us a lot of time to do interview with the affected users, who else is in the car and so on
  2. If Maybank has this contact tracing module in their internal app for employees, if there’s any confirmed cases on 1 employee, they can easily identify the high risk affected employees. Even if our government app has this function, but not all employees will install the government app and it will take time for Maybank to get the data from the government to stop the spread.
  3. If Community/township app, like EcoWorld and SP Setia has this module, it can also achieve the same purpose as point 2.

If you know anyone from the owners of large scale corporates app, super app or community app, please share with them and refer to us at if they are interested to implement on non-profit basis. We hope to fight COVID-19 outbreak together.