Sending and receiving data between two Bluetooth dongle

In this project, we will demonstrate how two Bluetooth dongles can be paired together and share data between them. To pair two Bluetooth dongle, one of them needs to be configured as Central and other needs to be configured as Peripheral. We already wrote a Python script that sends data back and forth between dongles.

In short :

  1. One dongle will take on the Central role and the other will take on the Peripheral role.
  2. Then they will connect to each other.
  3. The Central dongle will then start off sending a message; “Echo”.
  4. The Peripheral dongle will then receive the message and send it back to the Central dongle which in turn will receive it and send it back and so forth until the script is stopped.

Device Required:

  • Laptop
  • BleuIO – BLE Dongle

Software Tools Required : 

Step 1 : Install Python on both laptop and connect a USB Dongle on each of them.

Step 2 : For a quick setup, copy the following script and save it on your local directory as sps_example.py . You can also get the source code from our GITHUB PAGE.

Step 3: Change the COM-port in the script on both computers to match the ones your dongles is actually connected to. For the one that will be set up as the Central dongle you will also need to change the target_dongle_mac_address variable to the MAC address of your Peripheral dongle. You can get the MAC address by scanning for the other dongle while it’s advertising. To learn more about how to scan check out our scanning tutorial.

Step 4: Open up the command prompt, on both computers, in the directory where the script is located. Start the script by typing python sps_example.py and press Enter.

Step 5: You should now be prompted to enter 1 or 2 depending on what role the dongle should have. Set one as Peripheral and the other as Central. It is advisable to setup the Peripheral first as the Central will need someone to connect to.

You should now see in the terminal how the dongles send and recieve data to and from each other.

The script will run until you stop it.

And that is an example of how we can send data between two dongles. If you want to stop the script, you can simply press control C.

Full source also available on GitHub.

Project Video

Share this post on :

Plotting real-time graph from Bluetooth 5.0 device to Google Chrome

Hey there,

Here is a tutorial on how to plot a real-time graph of values to Google Chrome from Hibou Air Quality Monitor using BleuIO and javascript library chartjs.

For this project, I am using Bluetooth Low Energy USB dongle called BlueIO, which will act as a central device to retrieve data. Hibou Air Quality Monitor which will serve as a peripheral device to transmit the data. The script is simple to use and can be used for other purposes such as showing real-time air quality data; temperate, humidity, pressure, particle matters etc.

The data could be later stored on a cloud service of choice.

Things we need:

Before we start

The article assumes you have some general knowledge of how Bluetooth Low Energy (BLE) work. Since the Chrome Serial specification on Google Chrome is not finalized yet, you will have to go to enable the highlighted flag, and restart Chrome.

open chrome://flags/#enable-experimental-web-platform-features in chrome browser. ​

In this example, we are going to use JavaScript + html (and some CSS for styling) to setup the BleuIO and quickly start scanning.

Step 1:

Create a file called index.html and paste the following codes. This gives you basic layout of the page with connect, scan, and get data buttons.

<!DOCTYPE html>
<html lang="en">
<head>
<title>Smart Sensor Devices Web Bluetooth Example</title>
<meta charset="utf-8" />
<meta name="ssd" content="beaconexample" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" type="image/png" href="images/favicon.png" />

<script>
// Redirect to HTTPS if HTTP is requested.
if (window.location.protocol === "http:") {
window.location.href = "https:" + window.location.href.substring(5);
}
</script>
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
crossorigin="anonymous"
/>


</head>
<body>
<div class="container">
<div
id="carouselExampleFade"
class="carousel slide carousel-fade"
data-ride="carousel"
>
<div class="carousel-inner">
<div class="carousel-item active">
<div class="row">
<div class="col-md-9 caption">
<img src="images/logo.png" />
<h1>Bluetooth® low energy adapter</h1>
<a
class="btn btn-info btn-lg"
href="https://www.bleuio.com/"
target="_blank"
>Learn More</a
>
</div>
<div class="col-md-3">
<img
src="images/bleuIO_white_withlogo.png"
class="d-block w-100"
alt="..."
/>
</div>
</div>
</div>
<div class="carousel-item">
<div class="row">
<div class="col-md-9 caption">
<img src="images/logo.png" />
<h1>Create your own BLE applications</h1>
<a
class="btn btn-info btn-lg"
href="https://www.bleuio.com/"
target="_blank"
>Learn More</a
>
</div>
<div class="col-md-3">
<img
src="images/bleuIO_black_withlogo.png"
class="d-block w-100"
alt="..."
/>
</div>
</div>
</div>
<div class="carousel-item">
<div class="row">
<div class="col-md-9 caption">
<img src="images/logo.png" />
<h1>Quick, Innovative, Simple</h1>
<a
class="btn btn-info btn-lg"
href="https://www.bleuio.com/"
target="_blank"
>Learn More</a
>
</div>
<div class="col-md-3">
<img
src="images/bleuIO_black_withlogo.png"
class="d-block w-100"
alt="..."
/>
</div>
</div>
</div>
</div>
</div>
<!-- end carousel -->
</div>
<!-- end container -->
<div class="codesection">
<div class="container">
<h1>Web Sensor Plotter Example</h1>
<main class="main">
<div id="notSupported" class="hidden alert alert-danger">
Sorry, <b>Web Serial</b> is not supported on this device, make sure
you're running Chrome 78 or later and have enabled the
<code>#enable-experimental-web-platform-features</code> flag in
<code>chrome://flags</code> <br />
Open
<strong>
chrome://flags/#enable-experimental-web-platform-features</strong
>
in Google Chrome browser.
</div>

<br />
<button id="butConnect" type="button" class="btn btn-success">
Connect
</button>
<br /><br />
<div class="row">
<div class="col-md-3"><button id="butScan" type="button" disabled class="btn btn-primary">
Scan BLE Devices
</button></div>
<div class="col-md-3">
<select class="devices form-control" id="devices" onchange="getSelectedDevice(this)">
<option value="">Select a Device</option>
</select></div>
<div class="col-md-3"><button
id="butGetData"
type="button"
disabled
class="btn btn-primary"
>
Get Data
</button></div>
</div>


<br /><br />


<pre id="log" class="mt-5 d-none"></pre>

<div style="background: white;">
<canvas id="myChart"></canvas>
</div>


</main>
</div>
</div>
<div class="footer text-center mt-3">
Powered by <a href="https://www.bleuio.com/" target="_blank">BleuIO</a> .
A product of
<a href="http://smartsensordevices.com/" target="_blank"
>Smart Sensor Devices</a
>
</div>

<!-- end container -->
<!-- JS, Popper.js, and jQuery -->
<script
src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
crossorigin="anonymous"
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"
crossorigin="anonymous"
></script>
<script src="script.js" defer></script>

<script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/min/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
<script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@0.7.7"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-streaming@1.8.0"></script>

</body>
</html>

Step 2:

Create a file called script.js and paste the following codes.

"use strict";

let port;
let reader;
let inputDone;
let outputDone;
let inputStream;
let outputStream;
let isScanning = false;
let isGettingData = false;
let hibouDevices = [];
let rightDevice = false;
let scannedSensorData = []
var chartColors = {
red: 'rgb(255, 99, 132)',
orange: 'rgb(255, 159, 64)',
yellow: 'rgb(255, 205, 86)',
green: 'rgb(75, 192, 192)',
blue: 'rgb(54, 162, 235)',
purple: 'rgb(153, 102, 255)',
grey: 'rgb(96, 125, 139)'
};
var color = Chart.helpers.color;
const log = document.getElementById("log");
const butConnect = document.getElementById("butConnect");
const butScan = document.getElementById("butScan");
const butGetData = document.getElementById("butGetData");

document.addEventListener("DOMContentLoaded", () => {
butScan.addEventListener("click", clickScan);
butGetData.addEventListener("click", clickGetData);
butConnect.addEventListener("click", clickConnect);
const notSupported = document.getElementById("notSupported");
notSupported.classList.toggle("hidden", "serial" in navigator);
});
function randomScalingFactor() {
return (Math.random() > 0.5 ? 1.0 : -1.0) * Math.round(Math.random() * 100);
}
function onRefresh(chart) {
chart.config.data.datasets[0].data.push({
x: Date.now(),
y: scannedSensorData.p
});
chart.config.data.datasets[1].data.push({
x: Date.now(),
y: scannedSensorData.t
});
chart.config.data.datasets[2].data.push({
x: Date.now(),
y: scannedSensorData.als
});
chart.config.data.datasets[3].data.push({
x: Date.now(),
y: scannedSensorData.voc
});
chart.config.data.datasets[4].data.push({
x: Date.now(),
y: scannedSensorData.h
});
chart.config.data.datasets[5].data.push({
x: Date.now(),
y: scannedSensorData.pm25
});
}
var config = {
type: 'line',
data: {
datasets: [ {
label: 'Pressure',
backgroundColor: color(chartColors.red).alpha(0.5).rgbString(),
borderColor: chartColors.red,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
},
{
label: 'Temperature',
backgroundColor: color(chartColors.blue).alpha(0.5).rgbString(),
borderColor: chartColors.blue,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
},
{
label: 'Light',
backgroundColor: color(chartColors.orange).alpha(0.5).rgbString(),
borderColor: chartColors.orange,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
},
{
label: 'VOC',
backgroundColor: color(chartColors.grey).alpha(0.5).rgbString(),
borderColor: chartColors.grey,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
},
{
label: 'Humidity',
backgroundColor: color(chartColors.green).alpha(0.5).rgbString(),
borderColor: chartColors.green,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
},
{
label: 'PM 2.5',
backgroundColor: color(chartColors.purple).alpha(0.5).rgbString(),
borderColor: chartColors.purple,
fill: false,
cubicInterpolationMode: 'monotone',
data: []
}]
},
options: {
title: {
display: true,
text: 'Hibou - Realtime data'
},

scales: {
xAxes: [{
type: 'realtime',
realtime: {
duration: 20000,
refresh: 2000,
delay: 2000,
ttl:1000000,
onRefresh: onRefresh
},
gridLines: {
display:false
}
}],
yAxes: [{
scaleLabel: {
display: true,
labelString: 'value'
}
}]
},
plugins: {
zoom: {
// Container for zoom options
zoom: {
// Boolean to enable zooming
enabled: true,

// Zooming directions. Remove the appropriate direction to disable
// Eg. 'y' would only allow zooming in the y direction
mode: 'x',
}
}
},
tooltips: {
mode: 'nearest',
intersect: false
},
hover: {
mode: 'nearest',
intersect: false
}
}
};
var colorNames = Object.keys(chartColors);

/**
* @name connect
* Opens a Web Serial connection to a serial device such as a Smart USB Dongle 2.0 and sets up the input and
* output stream.
*/
async function connect() {
// - Request a port and open a connection.
port = await navigator.serial.requestPort();
// - Wait for the port to open.
await port.open({ baudRate: 9600 });

const encoder = new TextEncoderStream();
outputDone = encoder.readable.pipeTo(port.writable);
outputStream = encoder.writable;

let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable.pipeThrough(
new TransformStream(new LineBreakTransformer())
);

reader = inputStream.getReader();
readLoop().catch((error) => {
toggleUIConnected(false);
port = null;
log.textContent = "Dongle Disconnected!";
});
}

/**
* @name disconnect
* Closes the Web Serial connection.
*/
async function disconnect() {
// Close the input stream (reader).
if (reader) {
await reader.cancel();
await inputDone.catch(() => {});
reader = null;
inputDone = null;
}
// Close the output stream.
if (outputStream) {
await outputStream.getWriter().close();
await outputDone;
outputStream = null;
outputDone = null;
}
// Close the port.
await port.close();
port = null;
log.textContent = "Dongle Disconnected!";
}

/**
* @name clickConnect
* Click handler for the connect/disconnect button.
* Checks if port != null
* If true: Checks if any beacons is advertising or scans are running and stops the advertsing or scan if so. Then runs disconnect() and set toggleUIConnected to false.
* if false: Runs connect() then set toggleUIConnected to true.
*/
async function clickConnect() {
log.textContent = "";
if (port) {

// If disconnected while scanning the dongle will restart
if (isScanning) {
writeCmd("\x03");
butScan.textContent = "Scan BLE Devices";
isScanning = false;
}
await disconnect();
toggleUIConnected(false);
return;
}
await connect();
toggleUIConnected(true);
}

function getSelectedDevice(selectObject) {
var selectedDevice = selectObject.value;
localStorage.setItem("selectedDevice", selectedDevice);
}

/**
* @name clickScan
* Click handler for the Scan button.
* Checks if a scan is already running by checking the boolean isScanning.
* If isScanning = true: Stops scanning and goes back to peripheral mode, changes the button text and shows the beacon buttons. Finally sets isScanning = false.
* If isScanning = false: Goes into Central mode and starts scanning for ble devices. Also changes button text and hides the beacon buttons. Finally sets isScanning = true.
*/
function clickScan() {
console.log("SCAN BUTTON PRESSED");
if (isScanning) {
writeCmd("\x03"); // Ctrl+C to stop the scan
setTimeout(() => {
writeCmd("AT+PERIPHERAL"); // Set the dongle in Peripheral mode needed for advertising.
}, 500); // Waiting half a bit to make sure each command will get through separately.
isScanning = false;
butGetData.removeAttribute("disabled");
butScan.textContent = "Scan BLE Devices";

return;
}
hibouDevices = [];
writeCmd("AT+CENTRAL"); // Set the dongle in Central mode needed for scanning.
setTimeout(() => {
writeCmd("AT+GAPSCAN=3");
}, 500); // Waiting half a bit to make sure each command will get through separately.

butScan.textContent = "Stop Scanning...";
butGetData.setAttribute("disabled", "true");
log.classList.toggle("d-none", false);

isScanning = true;
}

/**
* @name clickGetData
* Click handler for the 'Get Data' button.
* Checks if a getData scan is already running by checking the boolean isGettingData.
* If isGettingData = true: Stops scanning and goes back to peripheral mode, changes the button text and shows the scan button. Finally sets isGettingData = false.
* If isGettingData = false: Goes into Central mode and starts scanning for ble devices data. Also changes button text and hides the scan button. Finally sets isGettingData = true.
*/
function clickGetData() {
console.log("GET DATA BUTTON PRESSED");
if (isGettingData) {
writeCmd("\x03"); // Ctrl+C to stop the scan
setTimeout(() => {
writeCmd("AT+PERIPHERAL"); // Set the dongle in Peripheral mode needed for advertising.
}, 500); // Waiting half a bit to make sure each command will get through separately.
isGettingData = false;
if(window.myChart){
window.myChart.destroy();
}
butScan.removeAttribute("disabled");
butGetData.textContent = "Get Data";
return;
}
writeCmd("AT+CENTRAL"); // Set the dongle in Central mode needed for scanning.
setTimeout(() => {
writeCmd("AT+FINDSCANDATA=FF5B07"); // Will just scan for adv data that contains 'FF5B07' which is the tag for Manufaturing Specific Data (FF) and our Company ID (5B07).
}, 500); // Waiting half a bit to make sure each command will get through separately.

butGetData.textContent = "Stop Getting Data...";
butScan.setAttribute("disabled", "true");
log.classList.toggle("d-none", false);

isGettingData = true;
var ctx = document.getElementById('myChart').getContext('2d');
window.myChart = new Chart(ctx, config);

}

/**
* @name readLoop
* Reads data from the input stream and displays it on screen.
*/
async function readLoop() {
while (true) {
const { value, done } = await reader.read();
if (value && (!isScanning && !isGettingData)) {
log.textContent += value + "\n";
}
if (value && isScanning) {
if(value === "SCAN COMPLETE") {
isScanning = false;
butScan.textContent = "Scan BLE Devices";
log.textContent += "\n" +"Scan Done" + "\n";
butGetData.removeAttribute("disabled");
log.classList.toggle("d-none", false);
}
let lineValueArray = value.split(" ");
if (lineValueArray[6] === "(HibouAIR)") {
if(lineValueArray[2]) {
hibouDevices.push("["+lineValueArray[2].replace("[1]", "") +"]");

}
log.textContent = "\n" + "hibouDevices found: " + hibouDevices.length + "\n";
}
if(value === "SCAN COMPLETE") {
var select = document.getElementById("devices");
hibouDevices.map(function(item){
var option = document.createElement("option");
option.value = item;
option.text = item;
select.appendChild(option)
});
}

}
if (value && isGettingData) {
if(value === "SCAN COMPLETE") {
isGettingData = false;
butGetData.textContent = "Get Data";
log.textContent += "\n" +"Scan Done" + "\n";
butScan.removeAttribute("disabled");
log.classList.toggle("d-none", false);
}

let lineValueArray = value.split(" ");
if(!rightDevice) { // The advdata is spread on two lines, the first identifies it,
if (lineValueArray[0] === localStorage.getItem("selectedDevice") && lineValueArray[3] === "[ADV]:") {
rightDevice = true;
//console.log("CONSOLE.LOG= "+value);
}
} else if (rightDevice) { // Second line contains the actual advdata string we need to parse
scannedSensorData = parseSensorData(lineValueArray[1]);
log.textContent = "\n" + "SensorData= " + JSON.stringify(scannedSensorData) + "\n";
//console.log(scannedSensorData.p)
//console.log("CONSOLE.LOG= "+value);
rightDevice = false;
}

}
if (done) {
console.log("[readLoop] DONE", done);
reader.releaseLock();
break;
}
}
}
/**
* @name writeCmd
* Gets a writer from the output stream and send the command to the Smart USB Dongle 2.0.
* @param {string} cmd command to send to the Smart USB Dongle 2.0
*/
function writeCmd(cmd) {
// Write to output stream
const writer = outputStream.getWriter();
console.log("[SEND]", cmd);

writer.write(cmd);
// Ignores sending carriage return if sending Ctrl+C
if (cmd !== "\x03") {
writer.write("\r"); // Important to send a carriage return after a command
}
writer.releaseLock();
}

/**
* @name LineBreakTransformer
* TransformStream to parse the stream into lines.
*/
class LineBreakTransformer {
constructor() {
// A container for holding stream data until a new line.
this.container = "";
}

transform(chunk, controller) {
// Handle incoming chunk
this.container += chunk;
const lines = this.container.split("\r\n");
this.container = lines.pop();
lines.forEach((line) => controller.enqueue(line));
}

flush(controller) {
// Flush the stream.
controller.enqueue(this.container);
}
}

/**
* @name toggleUIConnected
* Changes the text on butConnect depending on the action it actually will preform in the current state.
* @param {boolean} connected true if connected, false if disconnected.
*/
function toggleUIConnected(connected) {
let lbl = "Connect";
if (connected) {
lbl = "Disconnect";
butGetData.removeAttribute("disabled");
butScan.removeAttribute("disabled");
}
butScan.classList.toggle("disabled", !connected);
butGetData.classList.toggle("disabled", !connected);
butConnect.textContent = lbl;
}

/**
* @name parseSensorData
* Parse the data from advertising data string.
* @param {string} input advertising data string.
* @returns {object ={sensorid:{string}, p:{int}, t:{int}, h:{int}, als:{int}, pm1:{int}, pm25:{int}, pm10:{int}}}
*/
function parseSensorData(input) {
let counter = 13;
if (input.includes("5B070503")) {
counter = 17;
}
let sensorData = {
sensorid:
input[counter + 1] +
input[counter + 2] +
input[counter + 3] +
input[counter + 4] +
input[counter + 5] +
input[counter + 6],
p:
parseInt(
input[counter + 13] +
input[counter + 14] +
input[counter + 11] +
input[counter + 12],
16
) / 10,
t:
parseInt(
input[counter + 17] +
input[counter + 18] +
input[counter + 15] +
input[counter + 16],
16
) / 10,
h:
parseInt(
input[counter + 21] +
input[counter + 22] +
input[counter + 19] +
input[counter + 20],
16
) / 10,
voc:
parseInt(
input[counter + 25] +
input[counter + 26] +
input[counter + 23] +
input[counter + 24],
16
) / 10,
als: parseInt(
input[counter + 9] +
input[counter + 10] +
input[counter + 7] +
input[counter + 8],
16
),
pm1:
parseInt(
input[counter + 29] +
input[counter + 30] +
input[counter + 27] +
input[counter + 28],
16
) / 10,
pm25:
parseInt(
input[counter + 33] +
input[counter + 34] +
input[counter + 31] +
input[counter + 32],
16
) / 10,
pm10:
parseInt(
input[counter + 37] +
input[counter + 38] +
input[counter + 35] +
input[counter + 36],
16
) / 10}
return sensorData
}
// readLoop()
// .then((data) => { console.log(data)})
window.onload = function() {
//var ctx = document.getElementById('myChart').getContext('2d');
//window.myChart = new Chart(ctx, config);
};

This js has all the codes and uses Chrome Serial to

· Connect to your BleuIO Bluetooth dongle,

· Scan nearby devices using the AT-commands

· Receive and store the data

· Generate real time charts from the data.

All the functions used in the script are well commented for understanding.

Step 3:

Now create a style.css on the root folder and paste the following codes. They will give your site a clean look.

.hidden {
display: none !important;
}

.mb-button {
align-self: center;
background-color: #666;
border-radius: 100%;
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 2px 9px 1px rgba(0, 0, 0, 0.12),
0 4px 2px -2px rgba(0, 0, 0, 0.2);
height: 30px;
width: 30px;
}

.pressed {
background-color: #d81b60;
box-shadow: inset 0px 0px 5px #c1c1c1;
outline: none;
}
.caption {
margin-top: 100px;
}
pre {
padding: 20px;
color: #ffffff !important;
background-color: #222;
white-space: pre;
text-shadow: 0 1px 0 #000;
border-radius: 5px;
border-bottom: 1px solid #555;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4) inset,
0 0 20px rgba(0, 0, 0, 0.2) inset;
font: 16px/24px "Courier New", Courier, "Lucida Sans Typewriter",
"Lucida Typewriter", monospace;
}
.codesection {
background: #0d4c8d;
color: white;
padding: 20px 0;
min-height: 500px;
}

You can download the complete script from here.https://github.com/smart-sensor-devices-ab/Web-Hibou-Sensor-Plotter.git

Step 4:

Once you have everything ready, open the index.html file. Your page should look like this

Image for post

Now connect your BleuIO device to your computer and click connect. Wait for your device to show up on the port screen.

Select your device and press connect.

Image for post

Once the device is connected, you can scan for nearby devices. For this project I have added a filter so that it will only look for Hibou BLE devices. You will see a list of devices on the dropdown menu. We have a small console on the page that shows scan status and number of devices found. Now you can select a device from the dropdown and start getting data from the device.

Image for post

Once you click on get data after selecting a device, it will start to generate graphs using chartjs using real-time data from Hibou Air Quality Monitor.

In my script I am showing Pressure, Temperature, ALS, VOC, Humidity, PM2.5

You can customize your own chart by updating values. All the codes for charts are available on script.js

Done

Here is our real time chart showing on web browser.

Image for post

Follow this video if you find any difficulties.

Share this post on :

Interact with Bluetooth devices using Google Chrome

Bluetooth is a wireless technology that enables the transfer of data between Bluetooth enabled devices within a short distance. The Bluetooth® community is making significant improvement in wireless innovation every year.

Bluetooth Low Energy

Bluetooth Low Energy is known under many names: BLE, Bluetooth LE or Bluetooth Smart. The strength of Bluetooth Low Energy is indeed its very low energy consumption which is cost-effective with a significant battery lifetime. The BLE technology provides an easy and reliable interface, which is hugely appreciated by mobile application developers, consumer electronics manufacturers and engineers. It is an industry-specific technologywhich has become suitable for the Internet of Things (IoT) allowing a quick transfer of low-consuming data such as movement, humidity or temperature.

Usually, Bluetooth is used to pair mobile devices with other mobile or fixed devices. This could be your car, your earbuds, your smartwatch or your smart light. We have seen a lot of native app available that can interact with Bluetooth enabled devices, but how about connecting using a web browser? Yes, you can communicate with nearby Bluetooth devices using a web site in a secure and privacy-preserving way.

A BLE device may have two roles, central or peripheral:

Central: Central device manages the overall process by doing the scanning and connection to peripheral devices.

Peripheral: Peripheral device provides connections and data transfer with the Central device periodically.

Image for post

In this article, we will try to connect BLE device with a web browser.

Things we need :

* The BleuIO is Bluetooth low energy solution that can be used to create new BLE 5.0 applications in the fastest and easiest way. This device supports Windows 10, Linux and macOS.

Before we start

The article assumes you have some general knowledge of how Bluetooth Low Energy (BLE) work.

Since the Chrome Serial specification on Google Chrome is not finalized yet, you will have to go to enable the highlighted flag, and restart Chrome.

open chrome://flags/#enable-experimental-web-platform-features in chrome browser.

In this example, we’re going to use javascript + html (and some css for styling) to setup the BleuIO and quickly start scanning or advertising as an iBeacon or an Eddystone simply by pressing a button. For a quick setup, copy the following script and save it in your local directory. You can also get the source code from GITHUB PAGE.

Here is a demo of final output. View Demo

Image for post

index.html

Here we create a simple html page with a title, buttons and a field to display the output. We also add a textbox that will show up if the user doesn’t meet the requirements for Chrome Serial.

<!DOCTYPE html>
<html lang="en">
<head>
<title>Smart Sensor Devices Web Bluetooth Example</title>
<meta charset="utf-8" />
<meta name="ssd" content="beaconexample" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="shortcut icon" type="image/png" href="images/favicon.png" /> <script>
// Redirect to HTTPS if HTTP is requested.
if (window.location.protocol === "http:") {
window.location.href = "https:" + window.location.href.substring(5);
}
</script>
<link rel="stylesheet" href="style.css" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
crossorigin="anonymous"
/> <script src="script.js" defer></script>
</head>
<body>
<div class="codesection">
<div class="container">
<h1>Web Bluetooth Example</h1>
<main class="main">
<div id="notSupported" class="hidden">
Sorry, <b>Chrome Serial</b> is not supported on this device, make sure
you're running Chrome 78 or later and have enabled the
<code>#enable-experimental-web-platform-features</code> flag in
<code>chrome://flags</code>
</div> <br />
<button id="butConnect" type="button" class="btn btn-success">
Connect
</button>
<br /><br />
<button
id="butIbeacon"
type="button"
disabled
class="btn btn-warning"
>
Make iBeacon
</button>
<button id="butEddystone" type="button" disabled class="btn btn-info">
Make Eddystone Beacon
</button>
<button id="butScan" type="button" disabled class="btn btn-primary">
Scan BLE Devices
</button> <pre id="log" class="mt-5"></pre>
</main>
</div>
</div>
<div class="footer text-center mt-3">
Powered by <a href="https://www.bleuio.com/" target="_blank">BleuIO</a> .
A product of
<a href="http://smartsensordevices.com/" target="_blank"
>Smart Sensor Devices</a
>
</div> <!-- end container -->
<!-- JS, Popper.js, and jQuery -->
<script
src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
crossorigin="anonymous"
></script>
<script
src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"
integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"
crossorigin="anonymous"
></script>
<script
src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"
integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"
crossorigin="anonymous"
></script>
</body>
</html>

script.js

Here we is were we handle the functionality. We hook up our buttons with click-listeners and write the functions we need.

By running:

port = await navigator.serial.requestPort();

from the serial api we can get list of avalible com ports. Then we connect to that port and start listening for input from the dongle.

The “make beacon” button functions are setup with a static version of the iBeacon and Eddystone but you can just as easily hook up an input field and plug in the value in the ‘writeCmd()’ function in a similar fashion of that of the iBeacon and Eddystone examples.

In the ‘readLoop()’ function we just print out everything we get from the dongle to the ‘log’ element. But you could just as well listen for the response message after a command that signals that the action has been successful or not (like OK, ADVERTISING or ERROR etc.) and handle that and print what you like as response.

"use strict";let port;
let reader;
let inputDone;
let outputDone;
let inputStream;
let outputStream;
let isIbeaconAdv = false;
let isEddystonesAdv = false;
let isScanning = false;const log = document.getElementById("log");
const butIbeacon = document.getElementById("butIbeacon");
const butEddystone = document.getElementById("butEddystone");
const butConnect = document.getElementById("butConnect");
const butScan = document.getElementById("butScan");document.addEventListener("DOMContentLoaded", () => {
butIbeacon.addEventListener("click", clickIbeacon);
butEddystone.addEventListener("click", clickEddystone);
butScan.addEventListener("click", clickScan);
butConnect.addEventListener("click", clickConnect);
const notSupported = document.getElementById("notSupported");
notSupported.classList.toggle("disabled", "serial" in navigator);
});/**
* @name connect
* Opens a Chrome Serial connection to a serial device such as a Smart USB Dongle 2.0 and sets up the input and
* output stream.
*/

async function connect() {
// - Request a port and open a connection.
port = await navigator.serial.requestPort();
// - Wait for the port to open.
await port.open({ baudrate: 9600 }); const encoder = new TextEncoderStream();
outputDone = encoder.readable.pipeTo(port.writable);
outputStream = encoder.writable; let decoder = new TextDecoderStream();
inputDone = port.readable.pipeTo(decoder.writable);
inputStream = decoder.readable.pipeThrough(
new TransformStream(new LineBreakTransformer())
); reader = inputStream.getReader();
readLoop().catch((error) => {
toggleUIConnected(false);
port = null;
log.textContent = "Dongle Disconnected!";
});
}/**
* @name disconnect
* Closes the Chrome Serial connection.
*/

async function disconnect() {
// Close the input stream (reader).
if (reader) {
await reader.cancel();
await inputDone.catch(() => {});
reader = null;
inputDone = null;
}
// Close the output stream.
if (outputStream) {
await outputStream.getWriter().close();
await outputDone;
outputStream = null;
outputDone = null;
}
// Close the port.
await port.close();
port = null;
log.textContent = "Dongle Disconnected!";
}/**
* @name clickConnect
* Click handler for the connect/disconnect button.
* Checks if port != null
* If true: Checks if any beacons is advertising or scans are running and stops the advertsing or scan if so. Then runs disconnect() and set toggleUIConnected to false.
* if false: Runs connect() then set toggleUIConnected to true.
*/

async function clickConnect() {
log.textContent = "";
if (port) {
if (isEddystonesAdv || isIbeaconAdv) {
writeCmd("AT+ADVSTOP");
butIbeacon.textContent = "Make iBeacon";
butEddystone.textContent = "Make Eddystone Beacon";
isIbeaconAdv = false;
isEddystonesAdv = false;
}
// If disconnected while scanning the dongle will restart
if (isScanning) {
writeCmd("\x03");
butScan.textContent = "Scan BLE Devices";
isScanning = false;
}
await disconnect();
toggleUIConnected(false);
return;
}
await connect();
toggleUIConnected(true);
}/**
* @name clickIbeacon
* Click handler for the iBeacon button.
* Checks if an iBeacon is already running by checking the boolean isIbeaconAdv.
* If isIbeaconAdv = true: Stops advertising, changes the button text and shows the Eddystone button. Finally sets isEddystoneAdv = false.
* If isIbeaconAdv = false: Sets the advertising data to setup an iBeacon with a UUID and starts advertising.
* Also changes button text and hides the Eddystone button. Finally sets isIbeaconAdv = true.
*/

function clickIbeacon() {
console.log("IBEACON BUTTON PRESSED"); if (isIbeaconAdv) {
writeCmd("AT+ADVSTOP");
butEddystone;
butIbeacon.textContent = "Make iBeacon";
butEddystone.removeAttribute("disabled");
butScan.removeAttribute("disabled");
isIbeaconAdv = false;
return;
}
writeCmd("AT+ADVDATAI=5f2dd896-b886-4549-ae01-e41acd7a354a0203010400");
setTimeout(() => {
writeCmd("AT+ADVSTART=0;200;3000;0;");
}, 500); // Waiting half a bit to make sure each command will get through separately. butIbeacon.textContent = "Stop Beacon";
butEddystone.setAttribute("disabled", "true");
butScan.setAttribute("disabled", "true");
isIbeaconAdv = true;
}/**
* @name clickEddystone
* Click handler for the Eddystone Beacon button.
* Checks if an Eddystone beacon is already running by checking the boolean isEddystoneAdv.
* If isEddystoneAdv = true: Stops advertising, changes the button text and shows the iBeacon button. Finally sets isEddystoneAdv = false.
* If isEddystoneAdv = false: Sets the advertising data to setup an Eddystone beacon with a link to google.com and starts advertising.
* Also changes button text and hides the iBeacon button. Finally sets isEddystoneAdv = true.
*/

function clickEddystone() {
console.log("EDDYSTONE BUTTON PRESSED");
if (isEddystonesAdv) {
writeCmd("AT+ADVSTOP");
butEddystone.textContent = "Make Eddystone Beacon";
butIbeacon.removeAttribute("disabled");
butScan.removeAttribute("disabled");
isEddystonesAdv = false;
return;
}
writeCmd("AT+ADVDATA=03:03:aa:fe 0d:16:aa:fe:10:00:03:67:6f:6f:67:6c:65:07");
setTimeout(() => {
writeCmd("AT+ADVSTART=0;200;3000;0;");
}, 500); // Waiting half a bit to make sure each command will get through separately. //butIbeacon.classList.toggle("disabled", true);
butIbeacon.setAttribute("disabled", "true");
butScan.setAttribute("disabled", "true"); //butScan.classList.toggle("disabled", true);
butEddystone.textContent = "Stop Beacon";
isEddystonesAdv = true;
}/**
* @name clickScan
* Click handler for the Scan button.
* Checks if a scan is already running by checking the boolean isScanning.
* If isScanning = true: Stops scanning and goes back to peripheral mode, changes the button text and shows the beacon buttons. Finally sets isScanning = false.
* If isScanning = false: Goes into Central mode and starts scanning for ble devices. Also changes button text and hides the beacon buttons. Finally sets isScanning = true.
*/

function clickScan() {
console.log("SCAN BUTTON PRESSED");
if (isScanning) {
writeCmd("\x03"); // Ctrl+C to stop the scan
setTimeout(() => {
writeCmd("AT+PERIPHERAL"); // Set the dongle in Peripheral mode needed for advertising.
}, 500); // Waiting half a bit to make sure each command will get through separately.
isScanning = false;
butScan.textContent = "Scan BLE Devices";
butIbeacon.removeAttribute("disabled");
butEddystone.removeAttribute("disabled");
return;
}
writeCmd("AT+CENTRAL"); // Set the dongle in Central mode needed for scanning.
setTimeout(() => {
writeCmd("AT+GAPSCAN");
}, 500); // Waiting half a bit to make sure each command will get through separately. butScan.textContent = "Stop Scanning...";
butIbeacon.setAttribute("disabled", "true");
butEddystone.setAttribute("disabled", "true"); isScanning = true;
}/**
* @name readLoop
* Reads data from the input stream and displays it on screen.
*/

async function readLoop() {
while (true) {
const { value, done } = await reader.read();
if (value) {
log.textContent += value + "\n";
}
if (done) {
console.log("[readLoop] DONE", done);
reader.releaseLock();
break;
}
}
}/**
* @name writeCmd
* Gets a writer from the output stream and send the command to the Smart USB Dongle 2.0.
* @param {string} cmd command to send to the Smart USB Dongle 2.0
*/

function writeCmd(cmd) {
// Write to output stream
const writer = outputStream.getWriter();
console.log("[SEND]", cmd); writer.write(cmd);
// Ignores sending carriage return if sending Ctrl+C
if (cmd !== "\x03") {
writer.write("\r"); // Important to send a carriage return after a command
}
writer.releaseLock();
}/**
* @name LineBreakTransformer
* TransformStream to parse the stream into lines.
*/

class LineBreakTransformer {
constructor() {
// A container for holding stream data until a new line.
this.container = "";
} transform(chunk, controller) {
// Handle incoming chunk
this.container += chunk;
const lines = this.container.split("\r\n");
this.container = lines.pop();
lines.forEach((line) => controller.enqueue(line));
} flush(controller) {
// Flush the stream.
controller.enqueue(this.container);
}
}/**
* @name toggleUIConnected
* Toggles the butIbeacon & butEddystone buttons visable/hidden depending on if dongle is connected or not.
* Also changes the text on butConnect depending on the action it actually will preform in the current state.
* @param {boolean} connected true if connected, false if disconnected.
*/

function toggleUIConnected(connected) {
let lbl = "Connect";
if (connected) {
lbl = "Disconnect";
butIbeacon.removeAttribute("disabled");
butEddystone.removeAttribute("disabled");
butScan.removeAttribute("disabled");
}
butIbeacon.classList.toggle("disabled", !connected);
butEddystone.classList.toggle("disabled", !connected);
butScan.classList.toggle("disabled", !connected);
butConnect.textContent = lbl;
}

style.css

.hidden {
display: none !important;
}#notSupported {
padding: 1em;
background-color: red;
color: white;
margin-top: 1em;
margin-bottom: 1em;
}.mb-button {
align-self: center;
background-color: #666;
border-radius: 100%;
box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 2px 9px 1px rgba(0, 0, 0, 0.12),
0 4px 2px -2px rgba(0, 0, 0, 0.2);
height: 30px;
width: 30px;
}.pressed {
background-color: #d81b60;
box-shadow: inset 0px 0px 5px #c1c1c1;
outline: none;
}
.caption {
margin-top: 100px;
}
pre {
padding: 20px;
color: #ffffff !important;
background-color: #222;
white-space: pre;
text-shadow: 0 1px 0 #000;
border-radius: 5px;
border-bottom: 1px solid #555;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.4) inset, 0 0 20px rgba(0, 0, 0, 0.2) inset;
font: 16px/24px "Courier New", Courier, "Lucida Sans Typewriter", "Lucida Typewriter",
monospace;
}
.codesection {
background: #0d4c8d;
color: white;
padding: 20px 0;
min-height: 500px;
}

Run the web app by simply opening index.htmlin the Chrome web browser.

Make sure BleuIO is connected to your computer. Click Connect and wait a moment for your device to show up on the port screen.

Select your device and press Connect.

Image for post

Once the device is connected. You will be able to use all the example script we prepared — IBeacon, Eddystone Beacon, Scan.

Follow this video for more details.

Share this post on :

Distance Measuring Solution for COVID-19 using Bluetooth Low Energy

As the coronavirus pandemic continues, we’ve seen several social distancing, and contact tracing solution came in the market to stop the spread. Employers and businesses will want new devices to help keep social distancing when people return to work. In this case, Bluetooth technologies can be very useful.

When a Bluetooth device connects to another Bluetooth enabled device, it measures the signal strength as RSSI ( received signal strength indicator). The connection strength depends on the distance between the devices — The connection will be strong if two devices are nearby. As the device move apart, the connection weakens.

It is also possible to scan for nearby devices and read the RSSI value without establishing a connection, this makes it very suitable for looking after nearby devises as majority of people carries a smartphone with Bluetooth on.

BLE Measures Distance in 3 ways

Following are the three primary approaches to measure distance using BLE:

BLE RSSI (received signal strength indicator) Alone

This solution uses (Bluetooth Low Energy) BLE Received Signal Strength Indication (RSSI) to measure the distance between the receiver and the transmitter (scanner and advertising device) .

It is possible to increase accuracy by repeatedly scan the RSSI values and create an average over a fixed determined period.

Image for post

BLE with Ultra-wideband (UWB)

Another likely option is the combination of BLE with Ultra-wideband (UWB). UWB is a low energy radiofrequency technology that can transmit short-range, high bandwidth messages over the radio spectrum. UWB is best suited for location tracking, data collection and short-range indoor application. Combining UWB with RSSI helps get highly accurate measurements, but it has a higher BOM (bill of materials) cost due to the UWB chip.

BLE Based Proprietary Distance Measurement Technologies

BLE-based proprietary technologies can add distance measurement capabilities which makes it more accurate. It can combine Bluetooth LE data packets with constant tone frequency exchanges in order to generate the strong signals needed for more precise ranging. This technology can also be more accurate than RSSI alone and BLE with Ultra-wideband.

Developers can use smartphones Bluetooth technology that is already installed in the devices to perform contact tracing, but this approach has some problems related to privacy. Therefore, a BLE device that does not require any information from users is the right solution. For instance, BleuIO can be used to measure the distance without having to worry about privacy and security. The BleuIO is Bluetooth low energy solution that can be used to create new BLE 5.0 applications in the fastest and easiest way. Just use the AT Commands available on the device. Details about the AT commands will be found on getting started guide which will help anyone make a fast peripheral or central application (or both), on an incredibly low power platform without having to develop a single line of embedded code.

We have created a sample project on Get Bluetooth Device Distance Using BleuIO.

The device can be bought from https://www.bleuio.com/, and it will only cost $15.99.

Share this post on :

Turn a Raspberry Pi into Bluetooth Beacon.

Bluetooth is one of the innovative technology to transfer data wirelessly, build home automation systems, control other devices etc.

In this tutorial, we will learn about how to turn a Raspberry Pi into Bluetooth Beacon.

Requirements

Connect the BleuIO dongle to your Raspberry Pi.

To identify which device name the dongle is connected to, you will need to run:

ls /dev
Image for post

You might need to do it twice, once before you connect the dongle and once after to be able to identify which one is the device name. When starting up, the dongle will open up a COM port for the bootloader for 10 seconds to allow you to update the firmware (or flash your own application). You can update the firmware from here. Afterwards it will close that port and open a new port for the Smart USB Dongle 2.0 application which is the one we’re interested in here. You can run:

lsusb

It should list a device with the ID: 2dcf:6001 when the bootloader is active but change to 2dcf:6002 after 10 seconds when the application is running.

NOTE: The device name may vary and may not be the same as in the picture above.

You will need a serial communication program to communicate with the dongle. For this tutorial we will be using Minicom. You can get Minicom by running:

sudo apt-get install minicom

Now, to start using the dongle run the following command if, for example, your dongle is connected to the device name ttyACM0:

minicom -b 9600 -o -D /dev/ttyACM0
Image for post

Now try typing an AT-Command. For example

AT 

If you get an OK response that means the dongle is working.

To use these scripts you will need to have Python installed. Both Python2 and Python3 should work but the scripts are made with Python3 in mind. But there are comments where the script need to be edited to work with Python2. You will also need to install the module pySerial. The easiest way to install it is through pip (which you should already have after installing Python) by running:

Python2:

pip install pyserial

Python3:

python3 -m pip install pyserial

After connecting, you can use the following sample python script to set up your own iBeacon.

import serial
import timeconnecting_to_dongle = 0
print("Connecting to dongle...")
# Trying to connect to dongle until connected. Make sure the port and baudrate is the same as your dongle.
# You can check in the device manager to see what port then right-click and choose properties then the Port Settings
# tab to see the other settings
while connecting_to_dongle == 0:
try:
console = serial.Serial(
port='COM14',
baudrate=57600,
parity="N",
stopbits=1,
bytesize=8,
timeout=0
)
if console.is_open.__bool__():
connecting_to_dongle = 1
except:
print("Dongle not connected. Please reconnect Dongle.")
time.sleep(5)
print("\n\nConnected to Dongle.\n")
print("\n Welcome to the iBeacon example!\n\n")
new_input = 1
while 1 and console.is_open.__bool__():
# get keyboard input once
if (new_input == 1):
# Python 2 users
# input = raw_input("Enter the UUID... ")
new_input = input("Enter the UUID (x) string with Major (j), Minor (n) and TX (t) (format:"
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxjjjjnnnntt): ")
time.sleep(0.1)
# sends the commands to the dongle. Important to send the \r as that is the return-key.
console.write(str.encode("AT+ADVDATAI="))
console.write(new_input.encode())
console.write('\r'.encode())
time.sleep(0.1)
console.write(str.encode("AT+ADVSTART=0;200;3000;0;"))
console.write('\r'.encode())
out = ''
# let's wait one second before reading output (let's give device time to answer)
time.sleep(1)
while console.inWaiting() > 0:
out += console.read(console.inWaiting()).decode()
else:
if not out.isspace():
# We make sure it doesn't print the same message over and over again by setting [out] to blankspace
# after printing once and check for blankspace before print again
print(">>" + out)
out = " "

Full source also available on GitHub.

Save this script into a file called ibeacon.py
or you can name anything you like.

Now open the file using a command prompt by typing

python ibeacon.py

When you start the Python script, you should be able to see your iBeacon using a scanner App designed for Bluetooth Low Energy (BLE). Examples of scanner App can be BLE Scanner from Bluepixel Technologies.

Image for post

Here you can see , your device has started advertising.

You can also use Eddystone script.
Source code available here.

Share this post on :

Turn your Computer into an iBeacon

iBeacon technology allows Mobile Apps to understand their position on a micro-local scale, and deliver content to users based on location. It is a Bluetooth Low Energy technology.

BLE Advertising uses a one-way communication method. Beacons that want to be discovered can Advertise self-contained packets of data in set intervals. Smartphones collect these packets, which can be used for various applications to trigger things like push messages, prompts or app actions.

Beacons ideal for indoor location tracking because a standard BLE has a broadcast range of up to 100 meters.

iBeacon are defined by the Apple company including following parameters: UUID, Major and Minor

You can build your own beacon by defining your own parameter values.

What is UUID?

UUID stands for Universally Unique Identifier. It contains 32 hexadecimal digits, split into 5 groups, like this:

5f2dd896-b886–4549-ae01-e41acd7a354a0203010400

The UUID is a standard identifying system which allows a ‘unique’ number to be generated for a beacon network.

The purpose of the UUID is to identify iBeacons in your network, from all other possible beacons in networks not in your control.

What are Major and Minor values?

Major and Minor values are numbers assigned to your iBeacons, in order to identify individual iBeacon within your UUID network.

Minor and Major are unsigned integer values between 0 and 65535.

The iBeacon standard requires both a Major and Minor value to be assigned.

Device Needed

  • A laptop with usb port.
  • A BlueIO

*BlueIO is Bluetooth® low energy solution that can be used to create new BLE 5.0 applications in the fastest and easiest way.

How to use

Connect the BleuIO to your computer. It opens a virtual serial port (COM port) that you can use to send commands to and from the Bluetooth USB Adapter.

Image for post

Control Bluetooth USB Adapter using predefined commands that you can find on the website. click here

After connecting, you can use the following sample python script to set up your own iBeacon.

To use this scripts you will need to have Python installed. Both Python2 and Python3 should work but the scripts are made with Python3 in mind. But there are comments where the script need to be edited to work with Python2. You will also need to install the module pySerial. The easiest way to install it is through pip (which you should already have after installing Python) by running:

Python2:

pip install pyserial

Python3:

python3 -m pip install pyserial

Following is a sample python script for iBeacon. You can also get the source file from Github page.

 import serial 

 import time 

 connecting_to_dongle = 0 

 print(“Connecting to dongle…”) 

 # Trying to connect to dongle until connected. Make sure the port and baudrate is the same as your dongle. 

 # You can check in the device manager to see what port then right-click and choose properties then the Port Settings 

 # tab to see the other settings 

 <strong>while</strong> connecting_to_dongle == 0: 

 <strong>try</strong>: 

 console = serial.Serial( 

 port=’COM14′, 

 baudrate=57600, 

 parity=”N”, 

 stopbits=1, 

 bytesize=8, 

 timeout=0 

 ) 

 <strong>if</strong> console.is_open.__bool__(): 

 connecting_to_dongle = 1 

 except: 

 print(“Dongle not connected. Please reconnect Dongle.”) 

 time.sleep(5) 

 print(“\n\nConnected to Dongle.\n”) 

 print(“\n Welcome to the iBeacon example!\n\n”) 

 new_input = 1 

 <strong>while</strong> 1 and console.is_open.__bool__(): 

 # get keyboard input once 

 <strong>if</strong> (new_input == 1): 

 # Python 2 users 

 # input = raw_input(“Enter the UUID… “) 

 new_input = input(“Enter the UUID (x) string with Major (j), Minor (n) and TX (t) (format:” 

 “xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxjjjjnnnntt): “) 

 time.sleep(0.1) 

 # sends the commands to the dongle. Important to send the \r as that is the return-key. 

 console.write(str.encode(“AT+ADVDATAI=”)) 

 console.write(new_input.encode()) 

 console.write(‘\r’.encode()) 

 time.sleep(0.1) 

 console.write(str.encode(“AT+ADVSTART=0;200;3000;0;”)) 

 console.write(‘\r’.encode()) 

 out = ‘’ 

 # let’s wait one second before reading output (let’s give device time to answer) 

 time.sleep(1) 

 <strong>while</strong> console.inWaiting() > 0: 

 out += console.read(console.inWaiting()).decode() 

 <strong>else</strong>: 

 <strong>if</strong> not out.isspace(): 

 # We make sure it doesn’t print the same message over and over again by setting [out] to blankspace 

 # after printing once and check for blankspace before print again 

 print(“>>” + out) 

 out = “ “ 

Save this script into a file called ibeacon.py
or you can name anything you like.

Now open the file using a command prompt by typing

python ibeacon.py

When you start the Python script, you should be able to see your iBeacon using a scanner App designed for Bluetooth Low Energy (BLE). Examples of scanner App can be BLE Scanner from Bluepixel Technologies.

Image for post

Here you can see is your device has started advertising.

Now you can have your own iBeacon in no time. There are many other applications you can develop yourself. It’s a simple and excellent way to learn to program Bluetooth quickly.

Share this post on :