top of page

Sending Sensor Data to Smartphone over Bluetooth LE (Part 1: Open-Source Mobile App)

Updated: Apr 26

I started computer programming when I was in high school. Any piece of code that I've developed is accompanied by hardware and/or is part of a so-called "decision support software". One of the first programming languages that I learned was the 8051 assembly, a language you may have not even heard of! It was difficult to write in assembly and painful to debug. Over the years, I have tried many different programming languages and one that I got started with recently is an unusual one!

A while back I decided to try MIT App Inventor to develop a mobile app for Android. The goal was to send sensor data to smartphone over Bluetooth Low Energy. The result of that project was the SHUSHAN Mobile app that was available on Google Play until recently. When I started the project, it was with the intention to just get my hands dirty with mobile app development, but then I continued using the MIT App Inventor and was able to develop professional apps using this web application IDE.

The SHUHSAN Mobile app is extensive and has a lot of features:

  • Displays real-time sensor readings, and sensor metadata (serial number, firmware version, etc)

  • Logs geo-tagged sensor readings manually or automatically on smartphone (mobile-based data logging)

  • Collects and saves data from multiple Bluetooth LE-enabled devices

  • Can be used to give unique alphanumeric name to Bluetooth-enabled devices

  • Sends new settings and sensor calibration coefficients to DurUntash Bluetooth-enabled devices

  • Can program and operate Bluetooth-enabled irrigation controllers

In this article, I'm going to share a link to the project file (.aia) for and explain a simplified version of the SHUSHAN Mobile app (called SHUSHAN Mobile Open Source - OS). I will discuss the electronic hardware, Arduino program and communication protocol (to read sensors and send sensor data to smartphone) in Part 2 of this article.

Open-Source Mobile App

As explained the mobile app is developed using MIT App Inventor. This is not, however, an MIT App Inventor tutorial, so if you're new to this I refer you directly to their website. There you'll find tons of educational materials that can help you get started.

You can find the "aia" project file for the SHUSHAN Mobile-OS app here on GitHub. Please feel free to clone the repository, use as is or modify if you wish. The project blocks are self-explanatory for the most part, but I will explain what some of these blocks are for here.

User Interface

I'm going to start with explaining the "Designer" part of the app including the main components and how the simplified app (SHUSHAN Mobile Open-Source) works.

The app is designed to accommodate the following features:

  • scan for Bluetooth-LE devices

  • display real-time data from different sensors on your smartphone

  • display RSSI (signal strength) and battery charge in both numbers and beautiful icons

There are four sections/area in the main page:

  1. Logo

  2. Connection

  3. Device information

  4. Sensor information and data

The logo area is optional. The connection area is comprised of "connect" and scan (on the left next to the blue "connect" button) buttons. In the device information section, you can display device/node name, signal strength (RSSI) and battery voltage or charge level. The sensor area itself has two sections that are shown combined. At the top you can display the sensor name, status, and picture. At the bottom you can display up to four different sensor readings. The status LED simply changes color when a sensor is connected or disconnected, but you can work on it to change color if sensor readings were above/below certain threshold.

I've seen app that have four or even five individual buttons that do scan for nodes, connect, disconnect, etc. The SHUSHAN app has only two buttons. The scan button scans for Bluetooth-enabled devices, but if tapped again while connected, it will disconnect from the device. The "connect" button allows you to connect to a device that is selected from the list. If already connected, it allows you to disconnect.

As soon as you tap the scan button, a list of available Bluetooth-LE devices that are within the range and their UUID is valid appears. You just need to choose the node whose name matches your device and tap the "connect" button.

Once connected, the "connect" button turns green and its text changed to "Disconnect" indicating that you can tap the button to disconnect. As explained, alternatively you can also tap the scan button (twice) to disconnect and start a new search.

Scan for Bluetooth LE devices

Thanks to the structure of the MIT App Inventor IDE, the blocks are very self-explanatory. I'm going to start with the scan block so you can understand better how it works. My personal approach to programming is to keep routines (here blocks) as small as possible. So I break them down into smaller ones and use "call".

Whenever the scan button is taped/clicked, it checks to see whether we're already connected to a device or not. If connected, it simply calls the "disconnect" block, otherwise calls the "scan" routine.

The scan block first uses the classic Bluetooth extension to check if your smartphone's Bluetooth is on, otherwise it will warn you to turn it on first. The Bluetooth LE extension has a useful method (ScanForService) that allows you to filter out any device whose service UUID does not match yours. Without this filter you're going to all sort of Bluetooth device showing up in your search results.

Found devices are automatically listed in a ListView. This is exactly what I first found in the Bluetooth LE extension documentation. However, I wasn't happy with the results because the MAC address, name and RSSI were all showing up in one line. So I developed a filter ("FilterNodeNames" block) specifically for this purpose. The filter takes the list of found Bluetooth devices and filters everything but device name and its RSSI. You can see this in pictures below. I have kept the original method without the filter for comparison and just disabled it. Feel free to try both.

Select a device and connect

The "btnConnect" block is called when you tap/click the "Connect" button. As mentioned before, it has dual applications and is used to both connect to and disconnect from a Bluetooth LE-enabled device. The "connectByIndex" block checks to make sure you've selected a device before attempting to connect.

Receive sensor data

The "StringReceived" block is responsible for receiving and parsing data strings that sent by the Bluetooth device. The block may seem a bit complicated, but once you know the format of data strings it makes more sense. Every time a new data string is received, the block first updates the RSSI info by calling the "setRSSIIcon" block. The "setRSSIIcon" block is explained in the next section.

At DurUntash Lab, we have a developed a communication protocol for our devices including the ones that are Bluetooth-enabled such as the ISHTAR 1P-BLE sensor node and AVAN BLE handheld reader. I refer you to their user manuals to learn about this communication protocol. I will also briefly explain the data strings format for the ISHTAR 1P-BLE here. You can use the same data format and send sensor data to your smartphone using your own Bluetooth-enabled device.

Each string of data is transmitted over Bluetooth LE as human-readable ASCII text followed by a newline character (ASCII 10, or '\n'). The general sensor data format is as the following:

>[device code], [device number],[sensor channel code],[primary sensor reading],[temperature],[battery voltage],[measurement unit], [secondary sensor reading],

Here's what the terms in the data string mean if sent by the ISHTAR 1P-BLE:​

  1. Device code is "207" (read-only).

  2. Device number can be set to a number between 0 - 255 (0 or 255 by default).

  3. Sensor channel code varies depending on the sensor type and number of sensor channels on the device. The ISHTAR 1P-BLE has one sensor channel, therefore sensor type is the only determining factor. The channel codes for DurUntash sensors can be found in the user manual.

  4. Primary sensor reading depends on sensor type. Every reading is reported in its corresponding unit (% or dS/m) plus a constant value of 1000 (primary sensor reading = original value + 1000), which must be subtracted from the reading to obtain the correct value. For example, a soil moisture reading of 55 % would appear as 1055 (= 1000 + 55) on the serial port.

  5. Temperature is reported in degree Celsius (°C; default) or degree Fahrenheit (°F) depending on the settings, plus a constant value of 273. For example, a temperature of 25 °C is sent as 298 (= 273 + 25).

  6. Battery voltage is in volts (V).

  7. Measurement unit is "0" (default) or "1". A value of "0" means the temperature measurement unit is Metric and "1" means it is English.

  8. Secondary sensor reading depends on sensor type. For the APAS T1 soil moisture sensor and INSHU LWS, the secondary reading is raw soil moisture measurements or surface wetness from ADC after temperature compensation (no unit). For the HITA E0 electrical conductivity sensor, the secondary measurement is TDS in ppm.

For example, a general string of data sent by the ISHTAR node when the APAS T1 moisture and temperature sensor is connected will look like the following:


Display device information (RSSI & battery charge)

The "setRSSIIcon" block compares the RSSI value against certain values and chooses and displays an appropriate icon for it. If you're not already familiar with the concept of RSSI, it stands for Received Signal Strength Indicator. It is an estimated measure of power level at the receiver side. The larger the distance, the weaker the signal gets, leading to a lower overall data throughput. RSSI is measured in decibels (dBm) on a logarithmic scale and always negative. There is no exact relationship between RSSI and distance, but there are simple formula that you can use to convert negative RSSI to positive values in percent that reflect signal strength. In my program, however, I just used the original [negative] RSSI values.

Note: the RSSI value that is displayed is what received at the time of connecting to a new device, and unfortunately is not updated if the distance or signal strength changes.

The "CalculateBattChargePercentage" block is responsible for converting battery voltage to charge level (%). It also compares real-time charge level against predetermined thresholds and updates the battery icon. The block is not optimized and I'm sure you can make it smaller than that without compromising any of its functions.

Display sensor data

The last block ("DisplayData"), takes sensor readings and puts them in appropriate boxes in the sensor area. As explained above, each sensor has its own code and this is how the block determines where to put sensor readings. If no sensor is connected, the Bluetooth-enabled device still sends a string with code "100", which simply means no sensor. In this case, the block only cleans the boxes until actual sensor data is received.


MIT App Inventor is a great IDE for developing mobile apps. You can use it to develop professional apps for both Android and iOS. As you can see, it's very easy to send sensor data to your smartphone and display it in real-time. Please feel free to download the project file for the app, modify and use it in your projects. Leave comments in the comments section below if you had any questions.

Part 2

We have posted Part 2 of this article:



bottom of page