Red Bear Lab BLE Shield
Beacons are tiny modules which broadcast radio signals continuously or after regular intervals of time( in our case it is 100 ms).In this project we have used the above mentioned shield and Arduino Mega board to create a beacon.
This library has number of examples, one of which is Eddystone.h Including this header in our arduino code, we were able to create our arduino + BLE Sheild into a beacon. Ofcourse the practical implementation required us to rewrite basic implementation to suit our own use case.Starting point of this use case was how we broadcast a simple URL. Before going further, note that Eddystone frame format supports three ( now four) frames – URL, UID, TLM.
Eddystone allows for 31 Bytes of data to be transmitted in one frame.So if your URL exceeds 31 Bytes, you can use google shortner to shorten the URL.
After this follows the actual data.We will be transmitting our URL in this slot.There is a rule by which we encode our URL into the frame.More can be found out here
// Import libraries (EddystonBeacon depends on SPI)
#include <SPI.h>
#include <EddystoneBeacon.h>
//define pins (varies per shield/board)
// Adafruit Bluefruit LE 10, 2, 9
// Blend 9, 8, UNUSED
// Blend Micro 6, 7, 4
// RBL BLE Shield 9, 8, UNUSED
EddystoneBeacon eddystoneBeacon = EddystoneBeacon(EDDYSTONE_BEACON_REQ,
EDDYSTONE_BEACON_RDY, EDDYSTONE_BEACON_RST);
void setup() {
Serial.begin(9600);
delay(1000);
eddystoneBeacon.begin(-18, "http://goo.gl/TTY3vU");
Serial.println(F("Eddystone URL Beacon"));
}
void loop(){
eddystoneBeacon.loop();
}
EddystoneBeacon::EddystoneBeacon(unsigned char req, unsigned char rdy,
unsigned char rst) :
BLEPeripheral(req, rdy, rst),
_bleService("feaa"),
_bleCharacteristic("feab", BLERead | BLEBroadcast, MAX_SERVICE_DATA_SIZE)
{
this->setAdvertisedServiceUuid(this->_bleService.uuid());
this->setConnectable(false);
this->addAttribute(this->_bleService);
this->addAttribute(this->_bleCharacteristic);
}
There are couple of important things inside this definition.
Services and Characteristics- A call to this constructor initializes our beacon with service and characteristics.Service is a 128 bit data which acts as an identity of the eddystone frame.Next comes the characteristics which can be considered the main elements that give certain properties to your BLE device.You can customize in any which way you want to. Just that at the scanning end you have to already know this data.It acts as a carrier of the information.We can similarly create characteristic for transmission and reception.
SetConnectable is false because initially our beacon is in broadcast only mode
EddystoneBeacon.begin(...)
will begin broadcasting the power and URL data.void EddystoneBeacon::begin(char power, const char* uri) {
this->_power = power;
this->setURI(uri);
BLEPeripheral::begin();
this->_bleCharacteristic.broadcast();
}
EddystoneBeacon.loop()
will poll infinitely.We created a setup which consists of an electronic valve( 230V) , one 5V relay, one Push Button , an LED and the beacon. The idea was to simulate a scenario where a bike driver when in the vicinity of a petrol pump, will get notified on his/her smarphone about it.He/she can then approach the pump, tap on the notification and get redirected to a web-page/web-application which enabled him/her to interact with the petrol pump.Once he sees the webpage, he can pair his phone to the petrol pump( beacon ) and enter the volume of the fluid to be filled in his phone.On sending the command to fill, the beacon recieves it and turns the valve ON till the said amount is filled. At last, this guy can disconnect from the beacon.
To use google’s web bluetooth API, we need to have chrome 49 and above.Since we will be viewing our web application on android phone, one more constraint is that it should be Android 6+. A web application was made on IBM Bluemix with route https://thislinknolongerworks.mybluemix.net. The web application runs a node server at the back end.In the front end, what we see is html consisting of javascript.This is where we write our Web Bluetooth code.
bluetoothDevice = null;
var writeButton = document.querySelector('#fillUp');
navigator.bluetooth.requestDevice({ filters: [{ services:
[ '713d0000-503e-4c75-ba94-3148f18d941e' ] }] })
.then(device => {
Notice here [{services: […]}] is the serivice number for BLE tx and rx.
.then(device => {
bluetoothDevice = device;
return bluetoothDevice.connectGATT();
})
.then(server => {
// Getting Service...
return server.getPrimaryService('713d0000-503e-4c75-ba94-3148f18d941e');
})
.then(service => {
bleService = service;
//alert("primaryService passed!");
// Getting Characteristic...
return bleService.getCharacteristic('713d0003-503e-4c75-ba94-3148f18d941e');
})
.then(characteristic => {
writeCharacteristic = characteristic;
return bleService.getCharacteristic('713d0002-503e-4c75-ba94-3148f18d941e');
})
.then(characteristic => {
myCharacteristic = characteristic;
return myCharacteristic.startNotifications().then(() => {
myCharacteristic.addEventListener('characteristicvaluechanged',
handleNotifications);
});
})
.then(() => {
alert('Ready.');
})
.catch(error => { alert(error);
function handleNotifications(event) {
let value = event.target.value;
var textDecoder = new TextDecoder();
//alert(textDecoder.decode(value));
//document.getElementById("setVolume").value = textDecoder.decode(value);
var setVal = parseInt(textDecoder.decode(value));
setVal =(( setVal + 1 ) * 10);
//DONUT CHART
var donut = new Morris.Donut({
element: 'setVolume',
resize: true,
colors: ["#3c8dbc", "#f56954"],
data: [
{label: "Full%", value: setVal},
{label: "Empty%", value: 100-setVal}
],
hideHover: 'auto'
});
}
writeButton.addEventListener('click', function () {
// Get the bytes for the text
let input = document.getElementById("inputValue").value;
let encoder = new TextEncoder("utf-8");
let text = encoder.encode(input);
writeCharacteristic.writeValue(text);
});
Check out all the codes here and if you liked the post do follow for future updates!