Send BLE sensor data over MQTT using BleuIO

We’re living in the world of connected devices. The internet of things helps us live and work smarter, as well as gain complete control over our lives. One of the latest technological advancements in IoT is the MQTT gateway, which acts as a mediator between the cloud and IoT platforms.

MQTT stands for Message Queuing Telemetry Transport. It’s among the key communication protocols for the internet of things devices and local networks. It’s an ideal protocol for communication between smart devices or machine-to-machine communication.

What Is MQTT Gateway?

Generally, the MQTT gateway can be defined as an intermediary between any internet of things platform and sensors. It works by getting data from these sensors or smart devices and translating it into MQTT. It then transmits that data to either the internet of things platform or to the MQTT broker.

The publish/subscribe pattern

The publish/subscribe pattern (also known as pub/sub) provides an alternative to a traditional client-server architecture. In the client-server model, a client communicates directly with an endpoint. The pub/sub model decouples the client that sends a message (the publisher) from the client or clients that receive the messages (the subscribers). The publishers and subscribers never contact each other directly. In fact, they are not even aware that the other exists. The connection between them is handled by a third component (the broker). The job of the broker is to filter all incoming messages and distribute them correctly to subscribers.

MQTT Broker

A broker helps in handling clients in MQTT technology. It can manage hundreds, thousands, or millions of connected MQTT clients at once, depending on the implementation. Its main functions are;

  • Receiving information
  • Decoding and filtering the messages received
  • Determining which client will be interested in which message
  • Transmitting these messages to clients depending on their interests

The project

Let’s make a simple BLE 2 MQTT project that collects sensor data from a BLE Air quality monitor device called HibouAir and sends it to a free public MQTT broker.

For this project, we will use Flespi. You can choose any public or private MQTT broker as you like.

Steps

Requirments 

  • BleuIO dongle.
  • air quality monitor device HibouAir.
  • A public MQTT broker (Flepsi token) https://flespi.com/mqtt-broker
  • BleuIO Javascript library. https://www.npmjs.com/package/bleuio
  • A build tool for Javascript (parcel) https://parceljs.org/docs/

Get the Flespi token

  • Create an account at Flespi.
  • Log into the Flespi dashboard.
  • Copy the token

Download source file

Get the source file from https://github.com/smart-sensor-devices-ab/ble2mqtt_bleuio.git

And run npm install

In the root folder, we will see two Html files called index.html and subscribe.html and two js files called pub.js and sub.js

Index.html file collects sensor data from a BLE Air quality monitor device called HibouAir with the help of BleuIO. It has three buttons. connect, device info and Scan and Send BLE Data.

First we need to connect a BleuIO dongle into the computer and connect to it using connect button. The device info button will show BleuIO dongle status on console log. And the Scan and Send BLE data will scan for Air quality data and send it to the cloud. For this script I am scanning and collecting a fixed device with the board id of 0578E0. You can change the value in pub.js file line number 4

Here is the index.html file

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />
    <title>Publish</title>
  </head>
  <body>
    <div class="container mt-5">
      <button id="connect" class="btn btn-secondary">Connect</button>
      <button id="deviceinfo" class="btn btn-success d-none">
        Device Info
      </button>
      <button id="sendData" class="btn btn-primary">
        Scan and Send BLE Data
      </button>

      <h3 class="mt-5">Message Sent</h3>
      <div id="output"></div>
    </div>
  </body>
  <script src="./pub.js"></script>
</html>

After collecting advertised data, we try to decode it and get meaningful air quality data with co2, pressure, temperature, humidity, light values. Then we publish the data to Flepsi broker using topic name HibouAirTopic

The process is done in pub.js file.

Here is the pub.js file

const clientId = 'hibouair_' + Math.random().toString(16).substr(2, 8)
import * as my_dongle from 'bleuio'
import 'regenerator-runtime/runtime'
const sensorID = '0578E0'
import * as mqtt from "mqtt" 
document.getElementById('connect').addEventListener('click', function(){
  my_dongle.at_connect()
})
document.getElementById('deviceinfo').addEventListener('click', function(){
  my_dongle.ati().then((data)=>console.log(data))
})

const getTheBLEData = ( async()=>{
  return my_dongle.at_dual().then(()=>{
    return my_dongle.at_findscandata(sensorID,6).then((x)=>{
      let advData = x[x.length - 1].split(" ").pop()
      let positionOfID= advData.indexOf(sensorID);
      let tempHex = advData.substring(positionOfID+14, positionOfID+18)
      let temp = parseInt('0x'+tempHex.match(/../g).reverse().join(''))/10;

      let pressHex = advData.substring(positionOfID+10, positionOfID+14)
      let press = parseInt('0x'+pressHex.match(/../g).reverse().join(''))/10;

      let humHex = advData.substring(positionOfID+18, positionOfID+22)
      let hum = parseInt('0x'+humHex.match(/../g).reverse().join(''))/10;

      let lightHex = advData.substring(positionOfID+6, positionOfID+10)
      let light = parseInt('0x'+lightHex.match(/../g).reverse().join(''));

      let co2Hex = advData.substring(positionOfID+38, positionOfID+42)
      let co2 = parseInt('0x'+co2Hex);
      

      return {
        'CO2' :co2,
        'Temp' :temp,
        'Pressure':press,
        'Humidity':hum,        
        'Light':light,        
      }
    })
  })
})



//pass data
document.getElementById('sendData').addEventListener('click', function(){
    const host = 'wss://mqtt.flespi.io:443'

    const options = {
      keepalive: 60,
      clientId: clientId,
      protocolId: 'MQTT',
      username:'SET_YOUR_USERNAME',
      password:'SET_YOUR_PASSWORD',
      protocolVersion: 4,
      clean: true,
      reconnectPeriod: 1000,
      connectTimeout: 30 * 1000,
      will: {
        topic: 'HibouAirMsg',
        payload: 'Connection Closed abnormally..!',
        qos: 0,
        retain: false
      },
    }
    const client  = mqtt.connect(host, options)
    client.on('connect',()=>{
        console.log('connected mqtt client',clientId)

    })

    client.on('error', (err) => {
      console.log('Connection error: ', err)
      client.end()
    })

    client.on('reconnect', () => {
      console.log('Reconnecting...')
    })

    var topic = 'HibouAirTopic'

    // Publish
    setInterval(() => {

        getTheBLEData().then((x)=>{
          client.publish(topic, JSON.stringify(x), { qos: 0, retain: false })
        console.log("Message sent!", JSON.stringify(x));
        document.getElementById('output').innerHTML += JSON.stringify(x)+"<br>";
        })
      }, 5000);

    })

Make sure to set your username and password and change the Board ID of your device on pub.js file.

Subscribe.html file works as a subscriber which reads sensor data from the broker and shows it on the screen.

here is the subscribe.html file

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Subscribe</title>
  </head>
  <body>
    <h3>Message Received</h3>
    <div id="output"></div>
  </body>
  <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>

  <script src="sub.js"></script>
</html>

Again we need a js script that fetch data from cloud and show it on html file. Here is the sub.js file

const clientId = 'hibouair_' + Math.random().toString(16).substr(2, 8)

//const host = 'ws://broker.emqx.io:8083/mqtt'
const host = 'wss://mqtt.flespi.io:443'

const options = {
  keepalive: 60,
  clientId: clientId,
  protocolId: 'MQTT',
  username:'YOUR_USERNAME',
  password:'YOUR_PASSWORD',
  protocolVersion: 4,
  clean: true,
  reconnectPeriod: 1000,
  connectTimeout: 30 * 1000,
  will: {
    topic: 'HibouAirMsg',
    payload: 'Connection Closed abnormally..!',
    qos: 0,
    retain: false
  },
}

const client = mqtt.connect(host, options)
client.on('connect',()=>{
  console.log('connected mqtt client',clientId)
  client.subscribe('HibouAirTopic', { qos: 0 })
})
client.on('error', (err) => {
  console.log('Connection error: ', err)
  client.end()
})

client.on('reconnect', () => {
  console.log('Reconnecting...')
})


  
  // Received
client.on('message', (topic, message, packet) => {
  console.log(JSON.parse(message))
  //console.log('Received Message: ' + message + '\nOn topic: ' + topic)
  document.getElementById('output').innerHTML += message.toString()+"<br>";

})

To run the index.html we can just type

parcel index.html

Parcel JS can be installed from https://parceljs.org/

Project Video

Share this post on :

BleuIO Python library now supports firmware v2.1.3

BleuIO Python library is updated and supports firmware version 2.1.3 

Now you can easily access all the BleuIO AT commands using this library.
List of AT commands are available at https://www.bleuio.com/getting_started/docs/commands/

and how to access these AT commands using python library can be found at
https://pypi.org/project/bleuio/

Before starting to install our library, make sure you have the latest python installed on your system.

If you have never installed a library from PyPI, you must install the pip tool enabling you to download and install a PyPI package. There are several methods that are described on this page.

Now Install the library by running

pip install bleuio

Easy, right? pip automatically downloads and installs the most recent library on your system in the correct directory. To check that the installation went well, you can launch a Python interpreter and run the following lines:

from bleuio_lib.bleuio_funcs import BleuIo
my_dongle = BleuIo()
my_dongle.start_daemon()
print(my_dongle.ati())

Good luck on creating amazing Bluetooth Low Energy application using BleuIO

Share this post on :

Security Level 4 in Bluetooth LE connection

Protection of private information is essential for every wireless low energy device, from fitness bands to payment systems. Privacy mechanisms prevent devices from being tracked by untrusted devices.

Secure communications keep data safe while also preventing unauthorized devices from injecting data to trigger the system’s unintended operation.

In Bluetooth Low Energy (BLE), devices connected to a link can pass sensitive data by setting up a secure encrypted connection, which means making the data unreadable to all but the Bluetooth master and slave devices. 

A BLE connection is said to operate at a specific Security mode. Within each mode are several security levels. The required security mode/level of a connection may change from time to time, leading to procedures to increase that level.

To keep it simple, when two devices that initially do not have security wish to do something that requires security, the devices must pair first. This process could be triggered, for example, by a central device that is attempting to access a data value (a “characteristic”) on a peripheral device that requires authenticated access. 

Pairing involves authenticating the identity of two devices, encrypting the link using a Short-Term Key (STKs), and then distributing Long-Term Keys (LTKs) (for faster reconnection in the future, i.e., bonding) used for encryption.

The new security level of the connection is based on the method of pairing performed and this is selected based on the I/O capabilities of each device. The security level of any subsequent reconnections is based on the level achieved during the initial pairing.

Each device’s role is defined in the Security Manager (SM) portion of the BLE stack. They are:

  • Initiator: Always corresponds to the Link Layer Master and the GAP central.
  • Responder: Always corresponds to the Link Layer Slave and the GAP peripheral.

Security by means of encryption contains four levels

  • Level 1: No Security (No authentication and no encryption)
  • Level 2: Unauthenticated pairing with encryption
  • Level 3: Authenticated pairing with encryption
  • Level 4: Authenticated LE Secure Connections pairing with encryption

BleuIO‘s security feature can handle all four security levels to establish a secure BLE connection. Users can use Numeric Comparison, Just Works or Passkey Entry to make data transmission more secure when working with Bluetooth low energy applications using BleuIO. 

  • Numeric Comparison: In this scenario, both devices have a display unit capable of displaying a six-digit number. Both displays output the same number, and the user is asked to confirm that these numbers match. 
  • Passkey Entry: The Passkey Entry is primarily intended for the case that one device has a keyboard, but no display unit and the other device has at least a display unit, for example, a PC and a BLE keyboard scenario. The user is shown a six-digit number (from “000000” to “999999”) on the device with a display and then is asked to enter the number on the other device. If the value entered on the second device is correct, the pairing is successful.
  • Just Works: This model is primarily intended for the most constrained devices in I/O. The Just Works association model uses the Numeric Comparison protocol, but the user is never shown a number, and the application may ask the user to accept the connection. This method doesn’t offer protection against a Man in the Middle (MITM) attack, but it provides the same protection level against passive eavesdropping as the Numeric Comparison.

The table below is a reference for determining the pairing method based on the two devices I/O capabilities and each device’s role in the process.

Source: https://microchipdeveloper.com/wireless:ble-gap-security

Use the following AT commands to make your BLE connection more secure.

AT Commands :

  • AT+SETPASSKEY for setting or querying set passkey for passkey authentication.
  • AT+ENTERPASSKEY for entering the 6-digit passkey to continue the pairing request.
  • AT+SECLVL for setting or querying minimum security level used when connected to other devices.
  • AT+NUMCOMPA accepts a numeric comparison authentication request or enables/disabling auto-accepting numeric comparisons.
  • AT+GAPADDRTYPE Sets or queries what address type the dongle will use. Changing address type cannot be done while advertising or while connected to other devices. Read more at https://www.bleuio.com/getting_started/docs/commands/#atgapaddrtype

Following video shows how two BleuIO dongles can connect using passkey over security level 4.

In this example, the central dongle is using GAP IO CAPABILITY 2, which is ‘Keyboard only’ and the peripheral dongle is using GAP IO CAPABILITY 0, which is ‘display only’

The following table explains Input/Output Capabilities and supported security levels.

Share this post on :

Sensor data collection from STM32 and SHT85 using Bluetooth Low Energy

The project is showcasing a simple way of using the the BleuIO Dongle to advertise data that the STM32 reads from a sensor which is connected to the STM32 Nucleo-144.

Requirments :

  • A BleuIO dongle (https://www.bleuio.com/)
  • A SHT85 sensor (https://sensirion.com/products/catalog/SHT85/)
  • A board with a STM32 Microcontroller with a USB port. (A Nucleo-144 development board: NUCLEO-H743ZI2, was used developing this example. (https://www.st.com/en/evaluation-tools/nucleo-h743zi.html)
  • To connect the dongle to the Nucleo board we used a “USB A to Micro USB B”-cable with a USB A female-to-female adapter.)
  • STM32CubeIDE (https://www.st.com/en/development-tools/stm32cubeide.html)

When the BleuIO Dongle is connected to the Nucleo boards USB port, the STM32 will recognize it and start advertising the sensor values that it reads from the SHT85 along with the sensor serial number. It will update these values every 10 seconds.

Setup the project

Part 1 : Download the project

Get project HERE

https://github.com/smart-sensor-devices-ab/stm32_bleuio_SHT85_example

Either clone the project, or download it as a zip file and unzip it, into your STM32CubeIDE workspace.

Part 2 : Importing as an Existing Project

From STM32CubeIDE choose File>Import…

Then choose General>Existing Projects into Workspace then click ‘Next >’

Make sure you’ve choosen your workspace in ‘Select root directory:’

You should see the project “stm32_bleuio_SHT85_example”, check it and click ‘Finish’.

If you download the project as a zip file you will need to rename the project folder from ‘stm32_bleuio_SHT85_example-master’ to ‘stm32_bleuio_SHT85_example’

Connect the SDA to PF0 on the Nucleo board and SCL to PF1.

Then setup I2C2 in the STM32Cube ioc file like this:

Running the example

In STMCubeIDE click the hammer icon to build the project.

  • Open up the ‘STMicroelectronics STLink Viritual COM Port’ with a serial terminal emulation program like TeraTerm, Putty or CoolTerm.

Baudrate: 115200

Data Bits: 8

Parity: None

Stop Bits: 1

Flow Control: None

  • In STMCubeIDE click the green play button to flash and run it on your board. The first time you click it the ‘Run Configuration’ window will appear. You can just leave it as is and click run.
  • Connect the BleuIO Dongle.

Access sensor data from a web browser

We wrote a simple script that connects to the BleuIO dongle and reads advertised data from STM32.

For this script to work, we need

Steps

Create a simple Html file called index.html which will serve as the frontend of the script. This Html file contains some buttons that help connect and read advertised data from the remote dongle, which is connected to stm32.

<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <!-- Bootstrap CSS -->
    <link
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
      crossorigin="anonymous"
    />

    <title>STM32 Read sensor value</title>
  </head>
  <body>
    <div class="container mt-5">
      <h1>Sensor data collection from stm32 using Bluetooth Low Energy</h1>
      <button id="connect" class="btn btn-primary">Connect</button>
      <button id="getdata" class="btn btn-success">Get device data</button>
      <div id="loader"></div>
      <br />
      <div id="response" class="fw-bold"></div>

      <script src="./index.js"></script>
    </div>
  </body>
</html>

Create a js file called script.js and include it at the bottom of the Html file. This js file uses the BleuIO js library to write AT commands and communicate with the other dongle.

import * as my_dongle from 'bleuio'

//connect to BleuIO
document.getElementById('connect').addEventListener('click', function(){
  my_dongle.at_connect()
})
//get sensor data
document.getElementById('getdata').addEventListener('click', function(){
  document.getElementById('loader').innerHTML = 'Loading'
  //set the BleuIO dongle into dual role
    my_dongle.at_dual().then(()=>{
      // sensor id of the device that we are trying to get data from
      let sensorID='05084FA3'

      //look for advertised data of with the sensor id
        my_dongle.at_findscandata(sensorID,4).then(x=>{        

          //split the advertised data from the respnse
          let advdata= x[x.length-1].split(" ").pop()

          //trim the advertised string to only get sensor response
          const result = advdata.split(sensorID).slice(1).join(sensorID) 

          //get temperature and humidity value
          let temp = result.substring(0, 4);
          let hum = result.substring(4, 8);

          //convert from hex to decimal and device by 100
          temp = parseInt(temp, 16)/100
          hum = (parseInt(hum, 16)/100).toFixed(1)  

          document.getElementById('loader').innerHTML = ''
          document.getElementById('response').innerHTML = `Sensor ID : 05084FA3 <br/>
          Temperature : ${temp} °C<br/>
          Humidity : ${hum} %rH<br/>`              
        })
    })
    
  })

The script js file has two button actions; connect and read advertised data.

We also need to update the Sensor ID on line 13 of script js. The Sensor ID of this example project is 05084FA3, which we got from SHT85.

Therefore this script looks for advertised data that contains sensor ID 05084FA3. After getting advertised data , we split the temperature and humidity information and show it on our index.html page.

Now we need a web bundler. We can use parcel.js

Once parcel js installed, lets go to the root directory and type “parcel index.html”. This will start our development environment.

Lets open the script on a browser and select the right port where the dongle is connected.

The web script is available on web script folder of the GitHub repository.

Share this post on :

USB HID Enumeration with BleuIO to create BLE application

The BleuIO is a Bluetooth low energy USB dongle that can create new BLE 5.0 applications in the fastest and easiest way.

The BleuIO so far has been  supporting the USB Serial Port Profile (SPP).

A new firmware has been released to allow the use of USB Human Interface Device Profile (HID).

The USB HID is usually available in the operating system without the need of external drivers. The makes less dependency in developing BLE applications.

Choose your desired firmware for BleuIO by using built in bootloader and select between USB profiles:

  • Serial Port Profile (SPP) 
  • Human Interface Device Profile (HID)

HID Introduction

HID (Human Interface Device) defines a class of peripheral devices enables people to input data or interact directly with the computer, such as a mouse, keyboard, or joystick. The HID specification is a part of the USB standard, thus USB mice and other USB user input devices are HID compliant.

The host and the device are two entities in the HID protocol. The device is the entity that directly interacts with humans, such as a keyboard, mouse and BleuIO. The host communicates with the device and receives input data from the device in messages with 64 bytes size.

HID devices must meet a few general requirements that are imposed to keep the HID interface standardized and efficient. 

Demo application 

Bluetooth Special Interest Group (SIG) defines a HID profile that specifies how a device can support HID services over the Bluetooth LE protocol stack using the Generic Attribute Profile.

This example implementation shows how BleuIO can be used with the USB HID profile. The application allows to send BleuIO AT commands and displays the response on the screen.  

Share this post on :

C# Desktop application to get real-time BLE data from Air Quality Sensor

Bluetooth Low Energy (BLE) is a low power wireless technology used to connect devices. It is a popular communication method, especially in the Internet of Things era. Several devices around the house have a built-in Bluetooth transceiver, and most of them provide useful capabilities to automate jobs. This technology is widely used in the healthcare, fitness, beacons, security, and home entertainment industries. For that reason, it is really interesting to create a desktop application using C# that access BLE device data around the house.

In this example, we will create a simple C# windows form application to get real-time HibouAir environmental data using BleuIO. 

This script can be used to connect and view other BLE devices data.

Let’s start

First, let’s create a new project in visual studio and select C# windows form application from the list.

Choose a suitable name for your project.

Once the project is created, we will see a blank form screen where we will add buttons and labels to communicate with BleuIO graphically.


The application will connect to the BleuIO dongle to its given COM port from the script. You can change the port easily by going to line number 18.
We will have a disconnect button to disconnect BleuIO from the COM port.

The button Scan for HibouAir devices will look for nearby HibouAir devices and store them in an Array. The Combobox (dropdown item) next to it will load the stored device from where we can select a device to get its data.


The Get data button will show the real-time environmental data of this device.

The form will look like this.

The .cs file associated to this will have the following code.

Source code is available at https://github.com/smart-sensor-devices-ab/bluetooth_realtimedata_csharp

using System;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Threading;


namespace WindowsFormsApp1
{
    

    public partial class Form1 : Form
    {
        //Connect to Serial port
        //Replace port number to your comport
        SerialPort mySerialPort = new SerialPort("COM18", 57600, Parity.None, 8, StopBits.One);
        ArrayList device = new ArrayList();
        string ScannedData = "";
        public string selectedDevices = "";
        string advData = "";

        // HibouAir Advertise data decrypt and show output
        public String ParseSensorData(string input)
        {
            int counter = 17;
            string theData = " SensorID : " + input[counter + 1] +
              input[counter + 2] +
              input[counter + 3] +
              input[counter + 4] +
              input[counter + 5] +
              input[counter + 6] + "\n\n " +
              "Pressure : " + Convert.ToInt32(input[counter + 13].ToString() + input[counter + 14].ToString() + input[counter + 11].ToString() + input[counter + 12].ToString(), 16) / 10 + " mbar\n\n " +
              "Temperature : " + Convert.ToInt32(input[counter + 17].ToString() + input[counter + 18].ToString() + input[counter + 15].ToString() + input[counter + 16].ToString(), 16) / 10 + " °C\n\n " +
              "Humidity : " + Convert.ToInt32(input[counter + 21].ToString() + input[counter + 22].ToString() + input[counter + 19].ToString() + input[counter + 20].ToString(), 16) / 10 + " %rH\n\n " +
              "VOC : " + Convert.ToInt32(input[counter + 25].ToString() + input[counter + 26].ToString() + input[counter + 23].ToString() + input[counter + 24].ToString(), 16) / 10 + "\n\n " +
              "ALS : " + Convert.ToInt32(input[counter + 9].ToString() + input[counter + 10].ToString() + input[counter + 7].ToString() + input[counter + 8].ToString(), 16) + " Lux\n\n " +
              "PM 1.0 : " + Convert.ToInt32(input[counter + 29].ToString() + input[counter + 30].ToString() + input[counter + 27].ToString() + input[counter + 28].ToString(), 16) / 10 + " µg/m³\n\n " +
              "PM 2.5 : " + Convert.ToInt32(input[counter + 33].ToString() + input[counter + 34].ToString() + input[counter + 31].ToString() + input[counter + 32].ToString(), 16) / 10 + " µg/m³\n\n " +
              "PM 10 : " + Convert.ToInt32(input[counter + 37].ToString() + input[counter + 38].ToString() + input[counter + 35].ToString() + input[counter + 36].ToString(), 16) / 10 + " µg/m³"
              ;

            sensor_op.Text = theData.ToString();
            return theData;
        }


        public Form1()
        {
            InitializeComponent();    
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
            mySerialPort.Open();
            ArrayList device = new ArrayList();

        }

        
        //Store response from the dongle
        private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            
            SerialPort sp = (SerialPort)sender;
            string s = sp.ReadExisting();
            if (s.Contains("RSSI") && s.Contains("(HibouAIR)") )
            {
                device.Add(s);
                
            }
            if (selectedDevices != "")
            {
                label1.Invoke(new EventHandler(delegate { label1.Text = selectedDevices.Remove(0, 3); })); 
           
                if (s.Contains("[ADV]"))
                {
                    ScannedData=s;
                    
                   // output_data.Invoke(new EventHandler(delegate { output_data.Text += "TT: " + s + "\r\n"; }));
                }           
             }
            //output_data.Invoke(new EventHandler(delegate { output_data.Text += s + "\r\n"; }));


            //lbl_output.Invoke(this.myDelegate, new Object[] { s });
        }


       
        // Disconnect from COM port
        private void btn_disconnect_Click(object sender, EventArgs e)
        {
            mySerialPort.Close();
            Environment.Exit(0);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }



        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void btn_deviceList_Click(object sender, EventArgs e)
        {
            var inputByte = new byte[] { 13 };
            byte[] dualCmd = Encoding.UTF8.GetBytes("AT+DUAL");
            dualCmd = dualCmd.Concat(inputByte).ToArray();
            mySerialPort.Write(dualCmd, 0, dualCmd.Length);

            byte[] gapScanCmd = Encoding.UTF8.GetBytes("AT+GAPSCAN=2");
            gapScanCmd = gapScanCmd.Concat(inputByte).ToArray();
            mySerialPort.Write(gapScanCmd, 0, gapScanCmd.Length);
            

        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        // Load devices on dropdown
        private void dropdown_device_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(dropdown_device.Text == "Load Devices")
            {
                
                foreach (var a in device)
                {
                    dropdown_device.Items.Add(a);
                }
            }
            else
            {
                selectedDevices = dropdown_device.Text;
                string[] selectedDeviceID = selectedDevices.Split(' ');
                selectedDevices = selectedDeviceID[2];
                btnGetData.Visible = true;
            }
            
        }

        //get advertised data of selected device
        private void btnGetData_Click(object sender, EventArgs e)
        {


            var inputByte = new byte[] { 13 };
            byte[] gapScanCmd = Encoding.UTF8.GetBytes("AT+FINDSCANDATA=FF5B07");
            gapScanCmd = gapScanCmd.Concat(inputByte).ToArray();
            mySerialPort.Write(gapScanCmd, 0, gapScanCmd.Length);
            Thread.Sleep(500);
            byte[] bytes = Encoding.UTF8.GetBytes("\u0003");
            bytes = bytes.Concat(inputByte).ToArray();
            mySerialPort.Write(bytes, 0, bytes.Length);
            var array = ScannedData.Split('\n');
            int i = 0;
            //filter selected device data
            foreach (var a in array)
            {
                string kk = (string)a;
                if (kk.Contains(selectedDevices.Remove(0, 3)))
                {
                    var bleData = array[i].Split(' ');
                    advData = bleData[4];

                    var toPrint = ParseSensorData(advData);

                    break;
                }

                i++;

            }
            
        }
    }

    
}

As you can notice, I wrote COM18 to connect to the serial port because the BleuIO device on my computer is connected to COM18.
You can check your COM port from the device manager.
Let’s run the project and click on scan for HibouAir devices.

Here is a demo of this sample application.

Share this post on :

Multiple Connections in Bluetooth LE Central Device

Bluetooth low energy technology offers a suitable way of connecting smart devices. The term IoT or Internet of Things brings new technologies to transform and make the world in the era of connectivity. The IoT says that everything is connected, and Bluetooth has made it much easier to work. One central device can initiate and maintain connections with multiple Bluetooth Low Energy peripherals devices. 

The BleuIO is a Bluetooth low energy solution that can create new BLE 5.0 applications fastest and easiest way. Using this BleuIO’s multi-connection feature, we can easily connect to multiple BLE devices and transfer data between them.

This article will explain how to use BleuIO’s multi-connection features, connect to multiple BLE devices and transfer data between them. We will use three BleuIO dongles for this project: one central and two peripheral. The central dongle will connect to peripheral and send data simultaneously. 

We will create a simple python script that will help us do the task.

Requirements :

  1. 3 pcs BleuIO Dongle.
  2. Python 2.7 or Python 3.4 and newer
  3. pyserial 3.5

Task:

Step 1: 

Let’s create a python file called py_serial_transfer.py and copy the following code.

Source code is also available at GitHub

https://github.com/smart-sensor-devices-ab/ble_multi_connection_example.git
import serial
import time
import string
import random

target_dongle_mac_address = (
    "[0]40:48:FD:E5:2D:AF"  # Change this to the 1st peripheral's mac address.
)
target_dongle_mac_address2 = (
    "[0]40:48:FD:E5:2D:B5"  # Change this to the 2nd peripheral's mac address.
)
your_com_port = "COM7"  # Change this to the com port your dongle is connected to.

connecting_to_dongle = True
trying_to_connect = False
trying_to_connect2 = False

def id_generator(size=10, chars=string.ascii_uppercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

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:
    try:
        console = serial.Serial(
            port=your_com_port,
            baudrate=57600,
            parity="N",
            stopbits=1,
            bytesize=8,
            timeout=0,
        )
        if console.is_open.__bool__():
            connecting_to_dongle = False
    except:
        print("Dongle not connected. Please reconnect Dongle.")
        time.sleep(5)

print("Connected to Dongle.")

connected = "0"
connected2 = "0"
while 1 and console.is_open.__bool__():
    console.write(str.encode("AT+DUAL"))
    console.write("\r".encode())
    time.sleep(0.1)
    print("Putting dongle in Dual role and trying to connect to other dongle.")
    while connected == "0":
        time.sleep(0.5)
        if not trying_to_connect:
            console.write(str.encode("AT+GAPCONNECT="))
            console.write(str.encode(target_dongle_mac_address))
            console.write("\r".encode())
            trying_to_connect = True
        dongle_output2 = console.read(console.in_waiting)
        time.sleep(2)
        print("Trying to connect to Peripheral 1...")
        if not dongle_output2.isspace():
            if dongle_output2.decode().__contains__("\r\nCONNECTED."):
                connected = "1"
                print("Connected to 1st device!")                
                time.sleep(5)
            if dongle_output2.decode().__contains__("\r\nDISCONNECTED."):
                connected = "0"
                print("Disconnected!")
                trying_to_connect = False
            dongle_output2 = " "
    while connected2 == "0":
        time.sleep(0.5)
        if not trying_to_connect2:
            console.write(str.encode("AT+GAPCONNECT="))
            console.write(str.encode(target_dongle_mac_address2))
            console.write("\r".encode())
            trying_to_connect2 = True
        dongle_output2 = console.read(console.in_waiting)
        time.sleep(2)
        print("Trying to connect to Peripheral 2...")
        if not dongle_output2.isspace():
            if dongle_output2.decode().__contains__("\r\nCONNECTED."):
                connected2 = "1"
                print("Connected to 2nd device!")                
                time.sleep(5)
            if dongle_output2.decode().__contains__("\r\nDISCONNECTED."):
                connected2 = "0"
                print("Disconnected!")
                trying_to_connect2 = False
            dongle_output2 = " "
    while connected == "1" and connected2 =="1":        
        dongle_output3 = console.read(console.in_waiting)
        delay=10
        close_time=time.time()+delay
        i=0
        while True:
            myConIndex =  ('0000' if i%2 == 0 else '0001')
            console.write(str.encode("AT+TARGETCONN="))
            console.write(str.encode(myConIndex))
            console.write("\r".encode())
            console.write(str.encode("AT+SPSSEND="))
            console.write(str.encode(id_generator()+'-'+myConIndex))
            console.write("\r".encode())
            time.sleep(0.2)
            i+=1
            if time.time()>close_time:
                break
        console.write(str.encode("AT+SPSSEND=[DONE]\r"))
        time.sleep(0.2)
        print("Sending complete!\r\n")
        print("Exiting script...")
        exit()

This script will be used for the central BleuIO dongle. We need to find the port number of each dongle and the peripheral mac address.

Step 2:

Connect three BleuIO dongles on your PC. You can do the process on three different PC or Raspberry Pi.

I have connected both the central and the peripheral to one PC for this project.

After connecting the dongles, open device manager (windows) to find ports of each dongle.

On my PC, I have the BleuIO dongles connected on ports 7,8 and 18.

Let’s make COM7 the central , COM8 and COM18 as peripheral.

Now open the scripts and set the ports number on line 12. 

We also need to know the peripheral dongles mac address. 

To do that, we can simply advertise the dongle using AT+ADVSTART command .

  • Go to https://bleuio.com/web_terminal.html
  • Click on connect to BleuIO dongle
  • Select your port for peripheral
  • Type AT+ADVSTART

Do the same process for the other peripheral dongle.

Now both the peripheral dongle is advertising. We can do a gap scan from central to find their mac address. 

  • Go to https://bleuio.com/web_terminal.html
  • Click on connect to BleuIO dongle
  • Select your port for central
  • Type AT+DUAL (This will put the dongle in dual role)
  • Type AT+GAPSCAN

Now look for the dongle called BleuIO.

Update the script with the peripheral mac address (line 6,9)

Step 3 :

Now lets run the script.

Go to the script folder and type python py_serial_transfer.py

It will connect to both the peripheral dongles and send data randomly. 

You will see the responses on the web terminal screen. 

Please follow the video to get better understanding.

Share this post on :

Smart Sensor Devices’s BleuIO Earns KC Certification in South Korea

Smart Sensor Devices has earned the KC certification for its Bluetooth Low Energy USB dongle BleuIO, allowing it to be sold in South Korea.

As a global company, it is important that Smart Sensor Devices can serve customers around the globe. Any information communication equipment manufactured or imported for sale in South Korea must have KC certification. These products must have the KC logo and product certification number printed on the product. The certification ensures an electronic device is safe and meets all electromagnetic compatibility and radio frequency requirements.

“The KC certification is a big step for BleuIO as Smart Sensor Devices continues to expand our reach to other countries,” said Axel Hammar, Founder & CEO, Smart Sensor Devices. “This certification will allow us to work with South Korean companies and provide them with a more transparent and efficient supply chain.”

About BleuIO

This BleuIO is a Bluetooth low energy USB dongle that can create a new BLE 5.0 application fastest and easiest way. Just use the AT Commands available on the device. Details about the AT commands can be found on the getting started guide, which will help anyone make a fast peripheral or central application (or both) without developing a single line of embedded code. 

It is a fully integrated solution, providing MCU and Bluetooth radio in one chip, based on Dialog Semiconductor latest Bluetooth chip, DA14683. The FLASH based device permits field or boot upgradable, while the application is stored on FLASH memory. Custom settings can also be stored on FLASH memory or OTP for higher integrity. It supports Windows 10, Linux and macOS, Arduino and STM32.

For more information on BleuIO, visit bleuio.com

About Smart Sensor Devices

Smart Sensor Devices is a Swedish company working globally with the latest IoT solutions. We are located in Stockholm, the hottest hub for IoT inventions. Get in contact with us today and explore how you can become part of it! Our long-term experience in IoT devices and systems is crucial for giving your business the most for your investments, improving Time To Market, and lowering your risk.

Share this post on :

C# desktop application to connect to BLE devices using BleuIO

Bluetooth Low Energy (BLE) is a low power wireless technology used for connecting devices with each other. It is a popular communication method especially in the era of Internet of Things. Several devices around the house have a build-in buetooth transceiver and most of them provide really useful capabilitites to automate jobs. For that reason it is really interesting to create desktop application using C# that connects to the devices around the house and manage them.

In this example we are going to create a simple C# windows form application to communicate with BleuIO using SerialPort. This script can be used to create Bluetooth Low Energy application using C# with BleuIO.

Let’s start

As a first step lets create a new project in visual studio and select C# windows form application from the list.

Choose a suitable name for your project.

Once the project is created, we will see a blank form screen where we will add buttons and labels to communicate with BleuIO graphically.

We will have buttons that connects and disconnects from BleuIO. An input field that takes AT commands from the user and sends it to BleuIO using SerialPort. And a text area will display the response from BleuIO to the screen.

The form will look like this

The .cs file associated to this will have the following code.

Source code is available at https://github.com/smart-sensor-devices-ab/bluetooth_low_energy_csharp_WFA.git

using System;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    
    public partial class Form1 : Form
    {
        SerialPort mySerialPort = new SerialPort("COM18", 57600, Parity.None, 8, StopBits.One);
        public Form1()
        {
            InitializeComponent();            
            mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
            mySerialPort.Open();

        }

        private void button1_Click(object sender, EventArgs e)
        {
            
            
            lbl_test.Text = "Connected";
        }
        
        //print response from the dongle
        private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            string s = sp.ReadExisting();
            output_data.Invoke(new EventHandler(delegate { output_data.Text +=  s + "\r\n"; })); 

            //lbl_output.Invoke(this.myDelegate, new Object[] { s });
        }


        private void tb_cmd_TextChanged(object sender, EventArgs e)
        {
            
        }

        private void submit_cmd_Click(object sender, EventArgs e)
        {
            output_data.Text = "";
            byte[] bytes = Encoding.UTF8.GetBytes(tb_cmd.Text);
            var inputByte = new byte[] { 13 };
            bytes = bytes.Concat(inputByte).ToArray();
            mySerialPort.Write(bytes, 0, bytes.Length);           
        }

        private void btn_disconnect_Click(object sender, EventArgs e)
        {
            mySerialPort.Close();
            Environment.Exit(0);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void btn_stop_Click(object sender, EventArgs e)
        {
            byte[] bytes = Encoding.UTF8.GetBytes("\u0003");
            var inputByte = new byte[] { 13 };
            bytes = bytes.Concat(inputByte).ToArray();
            mySerialPort.Write(bytes, 0, bytes.Length);
        }

        private void output_data_TextChanged(object sender, EventArgs e)
        {

        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }
    }
}

As you can notice I wrote COM18 to connect to serial port because BleuIO device on my computer is connected to COM18.

You can check your COM port from device manager.

Lets run the project and click on connect button.

Once we are connected to BleuIO, we will be able to write AT commands using the input filed.

List of AT commands are available at https://www.bleuio.com/getting_started/docs/commands/

There is a stop button that write control+c to dongle and cancels current execution.

Here is a demo of this sample app.

Share this post on :

Create Bleutooth Low Energy Application with C# and BleuIO

Bluetooth Low Energy (BLE) is a low power wireless technology used for connecting devices with each other. It is a popular communication method especially in the era of Internet of Things. Several devices around the house have a build-in buetooth transceiver and most of them provide really useful capabilitites to automate jobs. For that reason it is really interesting to be able to create a main-device (like a PC) which will have an application that connects to the devices around the house and manage them.

In this example we are going to create a simple C# console application to communicate with BleuIO using SerialPort. This script can be used to create Bluetooth Low Energy application using C# with BleuIO.

Let’s start

As a first step lets create a new project in visual studio and select C# console application from the list.

This image has an empty alt attribute; its file name is image-1024x172.png

Choose a suitable name for your project and paste the following code to Program.cs file.

The source code is available at github.

using System;
using System.IO.Ports;
using System.Text;

namespace SerialPortExample
{
    class SerialPortProgram
    {                
        static SerialPort _port;
        static void Main(string[] args)
        {
            string portName;
            portName = SetPortName();
            _port = new SerialPort(portName,57600, Parity.None, 8, StopBits.One);
            // Instatiate this class
            SerialPortProgram serialPortProgram = new SerialPortProgram();
        }

        private SerialPortProgram()
        {
            _port.DataReceived += new
              SerialDataReceivedEventHandler(port_DataReceived);
            OpenMyPort();
            Console.WriteLine("Type q to exit.");
            bool continueLoop = true;
            string inputCmd;

            while (continueLoop)
            {
                inputCmd = Console.ReadLine();

                if (inputCmd == "q")
                {
                    continueLoop = false;
                    break;
                }
                else
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(inputCmd);
                    var inputByte = new byte[] { 13 };
                    bytes = bytes.Concat(inputByte).ToArray();
                    _port.Write(bytes, 0, bytes.Length);
                }
            }
        }

        private void port_DataReceived(object sender,
          SerialDataReceivedEventArgs e)
        {           
            // Show all the incoming data in the port's buffer
            Console.WriteLine(_port.ReadExisting());
        }

        //Open selected COM port
        private static void OpenMyPort()
        {
            try
            {
                _port.Open();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error opening my port: {0}", ex.Message);
                Environment.Exit(0);
            }
        }

        // Display Port values and prompt user to enter a port.
        public static string SetPortName()
        {
            string portName;

            Console.WriteLine("Available Ports:");
            foreach (string s in SerialPort.GetPortNames())
            {
                Console.WriteLine("   {0}", s);
            }

            Console.Write("Enter COM port value (ex: COM18): ");
            portName = Console.ReadLine();
            return portName;
        }

    }
}

For this script a BleuIO dongle connected to the computer.

When we run the application, it suggests all the available ports on the computer and asks to write the com port number where the BleuIO is connected.

Once we write the correct port number, it starts communicating with BleuIO via SerialPort.

The response of AT commands from the BleuIO will be shown on the screen.

Find the list of available AT commands at BleuIO getting started guide.

The application will terminate with control+c or type ‘q’.

Share this post on :