QCA402x Home Control App

Skill LevelArea of FocusOperating SystemPlatform/Hardware
IntermediateIoT, Bluetooth, Security, Smart HomeAndroidQCA 402x Wi-Fi/BLE/ZigBee

This project is designed to use the QCA4020 development kit to control a smart bulb, smart lock and smoke detector using a mobile app via Bluetooth Low Energy (BLE) channel, and also demonstrates home automation. You can control the bulb, turn it on/off, lock and unlock, sense smoke and send data in regular intervals.

The main objective of this project is to develop an android application that pairs with the home automation solution using the QCA4020 board over a BLE channel to control smart devices like a Smart Bulb (turn on & off), smart lock (lock & unlock) and smoke detector.

Parts Used:

Below are the items used in this project.

Resources of Home Control System on QCA4020 Development Board

  1. Mobile Phone with Android O operating system
  2. QCA4020 Development Board
  3. Smart Bulb
  4. Smart Lock (Servo Motor)
  5. Smoke Detector

Deploying the project

  1. Download code from the Gitlab Repository
  2. Compile the code and run the application from Android Studio to generate application (apk) file.

How to install Android application

APP Installation

  • ADB tool can be used to install the application (on both Windows and Linux) adb install qca_homecontrol.apk
  • Run the application in the phone.

How does it work?

The Android application will connect to the QCA4020 board via BLE. The Android application can read and write the QCA4020 board status using BLE GATT profile.

Prerequisite for BLE connection

The following code/ permission in the Android Manifest must be declared to detect the device in the application while scanning. This permission is needed to perform any Bluetooth communication, such as requesting a connection, accepting a connection, and transferring data.

  <uses-permission android:name="android.permission.BLUETOOTH" />

For the App to initiate device discovery or manipulate Bluetooth settings, you must declare the BLUETOOTH_ADMIN permission in addition to the BLUETOOTH permission.

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

Location permission is required because Bluetooth scan can be used to gather information about the location of the user.

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />    

Scanning for QCA4020 Device

This callback is used for searching device in the background:

  private BluetoothAdapter.LeScanCallback mLeScanCallback =
  new BluetoothAdapter.LeScanCallback() {
      @Override
      public void onLeScan(final BluetoothDevice device, 
                              int rssi,
                            byte[] scanRecord)
        {
          if (!bleDeviceList.contains(device)) {
              bleDeviceList.add(device);
              Logger.d(TAG, "Device : " + device);
          }
      }
  };

Pairing App with QCA4020 for Secure connection

Check the BLE security pin before connecting to the board

  BluetoothDevice mBluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  if (mBluetoothDevice != null) {
      try {
          byte[] pin = (byte[]) BluetoothDevice.class.getMethod("convertPinToBytes",String.class).invoke(BluetoothDevice.class, passkey);
          Method m = mBluetoothDevice.getClass().getMethod("setPin", byte[].class);
          m.invoke(mBluetoothDevice, pin);
      } catch (Exception e) {
          e.printStackTrace();
      }    

Initialize BLE connection

Once scanning is successful, the mobile app will list the devices (filter is applied to list only "QCA" prefixed device names) on the screen, clicking on a device will connect to the QCA4020 board. The connection to the board is made via GATT profile and BluetoothGattCallback callback will provide onConnectionStateChange() overridden method to update on the connection state.

  private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        String intentAction;
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_CONNECTED;
            broadcastUpdate(intentAction);
            Logger.i(TAG, "Connected to GATT server.");
            // Attempts to discover services after successful            connection.
            Logger.i(TAG, "Attempting to start service discovery:" 
                    +mBluetoothGatt.discoverServices());
        }

Discover QCA4020 board service

After successful connection with the QCA4020 board, the mobile app will be able to read the BLE services. The GATT callbacks onServicesDiscovered() overridden method will be implemented for finding service on QCA4020 board.

  @Override
  public void onServicesDiscovered(BluetoothGatt gatt, int status) {
      if (status == BluetoothGatt.GATT_SUCCESS) {
          broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
      } else {
          Logger.i(TAG, "onServicesDiscovered received: " + status);
      }
  }    

Smoke Sensor connected to QCA4020 board

A smoke detector is a device that senses smoke.
BLE Properties set: NOTIFY
Below method is for supporting notification from the board.

  public void notifyData(UUID SERVICE, UUID CHARACTERISTIC) {
    try {
        if (mBluetoothGatt != null) {
            BluetoothGattCharacteristic characteristic = mBluetoothGatt.getService(SERVICE).getCharacteristic(CHARACTERISTIC);
            mBLEService.setCharacteristicNotification(characteristic, true);
            mBLEService.readCharacteristic(characteristic);
        }
    } catch (Exception e) {
        Logger.d(TAG, "Exception in notifyData() -> " + e);
    }
  }   

On notification, it will call the callback onCharacteristicChanged() overridden method for to receive data from the board.

  @Override
  public void onCharacteristicChanged(BluetoothGatt gatt,
                                      BluetoothGattCharacteristic characteristic) {
      String str = null;
      try {
          str = new String(characteristic.getValue(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      }
      if (str != null)
          if(characteristic.getUuid().equals(SMOKE_SENSOR_CHARACTERISTIC)) {
              broadcastUpdate(ACTION_SMOKE_DATA_AVAILABLE, characteristic);
          }else {
          broadcastUpdate(ACTION_BULB_DATA_AVAILABLE,characteristic);
          }
  }
}; 

Smart Bulb connected to QCA4020 board

Smart bulbs can be controlled through a mobile app, and individual bulbs can be programmed to change output in a specific manner.

BLE Properties set: WRITE and NOTIFY.

NOTIFY:

Below method is for supporting notification from the board.

  public void notifyData(UUID SERVICE, UUID CHARACTERISTIC) {
    try {
        if (mBluetoothGatt != null) {
            BluetoothGattCharacteristic characteristic = mBluetoothGatt.getService(SERVICE).getCharacteristic(CHARACTERISTIC);
            mBLEService.setCharacteristicNotification(characteristic, true);
            mBLEService.readCharacteristic(characteristic);
        }
    } catch (Exception e) {
        Logger.d(TAG, "Exception in notifyData() -> " + e);
    }
  }

On notification, it will call the onCharacteristicChanged() overridden method to receive data from board.

  @Override
  public void onCharacteristicChanged(BluetoothGatt gatt,
                                      BluetoothGattCharacteristic characteristic) {
      String str = null;
      try {
          str = new String(characteristic.getValue(), "UTF-8");
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      }
      if (str != null)
          if(characteristic.getUuid().equals(SMOKE_SENSOR_CHARACTERISTIC)) {
              broadcastUpdate(ACTION_SMOKE_DATA_AVAILABLE, characteristic);
          }else {
          broadcastUpdate(ACTION_BULB_DATA_AVAILABLE,characteristic);
          }
    }
  };

WRITE:

Sending data to the board will achieve by calling below method

  public void writeData(byte[] val,UUID SERVICE, UUID CHARECTERISTIC)
  {
      try {
          BluetoothGattCharacteristic characteristicSsid =  mBluetoothGatt.getService(SERVICE).getCharacteristic(CHARECTERISTIC);
          characteristicSsid.setValue(val);
          mBLEService.writeCharacteristic(characteristicSsid);
      }catch (Exception e)
      {
          if(context != null){
              Toast.makeText(context, R.string.toast_write_failed,Toast.LENGTH_SHORT).show();
          }
      }
  }    

If write is successful, it will call the onCharacteristicWrite() overridden method for data to be sent to board.

  @Override
  public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
      byte[] bytes = characteristic.getValue();
      try {
          gatt.readCharacteristic(characteristic);
          Logger.d(TAG, new String(bytes, "UTF-8"));
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      } 
  }

Smart Lock in QCA4020 board

The QCA4020 controls a electromechanical lock, which is designed to perform locking and unlocking operations on a door when it receives such instructions from an authorized device via BLE

BLE Properties set: READ and WRITE.

READ:

This below method is for reading data from the board.

  public String readStatus(UUID SERVICE, UUID CHARECTERISTIC, Activity context) {
    try {
        if (mBluetoothGatt != null) {
            BluetoothGattCharacteristic characteristic = mBluetoothGatt.getService(SERVICE).getCharacteristic(CHARECTERISTIC);
            mBLEService.readCharacteristic(characteristic);
            byte[] value = characteristic.getValue();
            Logger.i(TAG,value+"");
            if(!(Arrays.toString(value).contains("null"))){
                status = convert(value);
            }
            Logger.i(TAG,status);
        }
    }catch (Exception e)
    {
        Toast.makeText(context,R.string.toast_read_failed,Toast.LENGTH_SHORT).show();
        e.printStackTrace();
    }
    return status;
    }

If read is successful, it will call the onCharacteristicRead() overridden method to receive data from board.

  @Override
  public void onCharacteristicRead(BluetoothGatt gatt,                                        
  BluetoothGattCharacteristic characteristic, int status) {
  
  }

WRITE:

Sending data to the board will be achieved by calling below method

  public void writeData(byte[] val,UUID SERVICE, UUID CHARECTERISTIC)
  {
      try {
          BluetoothGattCharacteristic characteristicSsid =  mBluetoothGatt.getService(SERVICE).getCharacteristic(CHARECTERISTIC);
          characteristicSsid.setValue(val);
          mBLEService.writeCharacteristic(characteristicSsid);
      }catch (Exception e)
      {
          if(context != null){
              Toast.makeText(context, R.string.toast_write_failed,Toast.LENGTH_SHORT).show();
          }
      } 

If write is successful, it will call the onCharacteristicWrite() overridden method for whenever it receives data from board.

  @Override
  public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
      byte[] bytes = characteristic.getValue();
      try {
          gatt.readCharacteristic(characteristic);
          Logger.d(TAG, new String(bytes, "UTF-8"));
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      } 
  }

Power On the QCA4020

Power on the QCA4020 via the power button, and the QCA4020 will initialize BLE and advertise automatically with HOME AUTOMATION service getting registered.

Launch the application

Launch “QDN-HomeControl-App” from the home screen

Launch the application on the Android Smartphone

Application Screens Flow

Application Screen flow of the Android application to connect to the QCA4020 board to communicate via BLE channel to control the Smart end devices:

Application screen transitions

Once the App is launched, it will start scanning the BLE devices in its proximity. If the QCA4020 board is available, it will be discovered and displayed in the list on the screen.

Users can select the QCA4020 board from the list to connect via secure BLE channel. In this screen, the user can initiate Re-Scan by clicking the Scan button on the top Action bar.

The user can also see the details of the application version on selecting the Setting icon on the Action bar.

Application screen showing the QCA4020 Development Boards found over BLE

After connecting to the board via BLE, the phone displays the device details screen.

On this screen, the user can control the BLE smart bulb and smart lock. There is a live graph plotted for the smart smoke detector. The data for the smoke detector notifies the application periodically and the graph is updated accordingly. The graph is shown for an hour of data.

On clicking the back button, the application gets disconnected with the QCA4020 board and returns to the home screen with BLE Scan process.

Application screen showing the status of connected devices.

Application screen showing the status of connected devices.

NameEmailTitle/Company
Rakesh Sankar[email protected]Sr. System Architect - GlobalEdge Software, Ltd
Shivanand Pujar[email protected]Project Manager - GlobalEdge Software, Ltd
Akshay Kulkarni[email protected]Technical Lead - GlobalEdge Software, Ltd
Snehalata Vajjaramatti[email protected]Sr. Software Engineer - GlobalEdge Software, Ltd
Puja Kumari[email protected]Android Developer - GlobalEdge Software, Ltd