Mohanad's "Blog" πŸ€“πŸ‘‹

How to use Bluetooth Beacons in positioning problem - part 1

[Recently, I was working on a project to find the position of a target point (e.g. mobile phone), in an indoor environment. Many technologies are being used in this area including WIFI, Bluetooth, RFID and all kind of sensors you can ]{style="font-size: 14px;"}[imagine]{style="font-size: 14px;"}[ on your mobile phone.]{style="font-size: 14px;"}

[In this article, I will explain my experiment in detecting position based on Bluetooth beacons, I used three ]{style="font-size: 14px;"}[estimote]{style="font-size: 14px;"}[ beacons, with a Raspberry pi 3 to be as the target point that I want to detect its position.]{style="font-size: 14px;"}

[In order to detect the position of the target point, we need to read the received strength signal indication RSSI that is received by the Raspberry Pi. The received RSSI value will allow us to find the approximate distance between the beacon and the target point. Knowing the distance will allow us to find the position using Trilateration algorithm.]{style="font-size: 14px;"}

[First,]{style="font-size: 14px;"}[ we need to make our raspberry pi be able to sense and read other Bluetooth devices around of it, to do so I found a node.js library that can be used to discover beacon devices around of it. It called Noble, this library is supported on Windows, ]{style="font-size: 14px;"}[Linux]{style="font-size: 14px;"}[, and Mac OS. I won’t cover the installation of that package since the installation is beyond the scope of this article. Now I will describe a small script written using Noble library to read beacons values.]{style="font-size: 14px;"}

var noble = require('noble');

noble.on('stateChange', function(state) {
  if (state === 'poweredOn') {    
    noble.startScanning([], true) //allows dubplicates while scanning
    console.log('Start scanning...');
  } else {
    noble.stopScanning();
  }
});

noble.on('discover', function(peripheral) { 
  var macAddress = peripheral.uuid;
  var rssi = peripheral.rssi;
  var localName = peripheral.advertisement.localName; 
  var serviceData = peripheral.advertisement.serviceData;
  var UUID = "undefined";
  if (serviceData && serviceData.length) {
    UUID = serviceData[0].data.toString('hex');
  }
  var distance = calculateDistance(rssi);

  var name = checkBluetoothBeacon(UUID);
  if (name != -1) {
    console.log('Found device: ', macAddress, ' RSSI:', rssi, ' Name:', name, ' Estimated Distance: ' , distance.toFixed(2));         
    writeCSV(name, rssi, distance.toFixed(2));
  }
});

[In the code above I keep listening to beacons and reading RSSI values in order to calculate the approximate distance between each beacon and my target point. To find the distance I used path loss model, as shown in equation (2).]{style="font-size: 14px;"}

[]{style="font-size: 14px;"}

[where the pl(d0) is the received power at reference distance d0 (usually one meter). While n is the path loss component, its value differs between indoor and outdoor environment, for ]{style="font-size: 14px;"}[indoor]{style="font-size: 14px;"} [environment]{style="font-size: 14px;"}[ it can have values between 1.6 – 1.8. The distance can be calculated then using equation (3).]{style="font-size: 14px;"}

[]{style="font-size: 14px;"}

[The following code represents the routine of calculating the approximate distance.]{style="font-size: 14px;"}

/**
* This function to return only estimote beacons based on their uuid
* Usful to not have unwanted bluetooth devices
*/
function checkBluetoothBeacon(uuid) {
  switch (uuid) {
    case '008a24afa82d271283de25c950248e5529914440':
      return 'Blueberry';
      break;
    case '00005a2bf63f7ad4d465edcd6d1c40842e914440':
      return 'ice';
      break;
    case '0077426e6764cfba96b54ceab8bff1bb0f914440':
      return 'mint';
      break;
    default: 
      return -1;
  }
}


function calculateDistance(rssi) {

  var txPower = -60 //hard coded power value. Usually ranges between -59 to -65

  if (rssi == 0) {
    return -1.0; 
  }

  var d = Math.pow(10, (txPower - rssi) / 17);
  return d;


  var ratio = rssi*1.0/txPower;
  if (ratio < 1.0) {
    return Math.pow(ratio,10);
  }
  else {
    var distance =  (0.89976)*Math.pow(ratio,7.7095);    
    return distance;
  }
}

I will continue to calculate the position in another post