Create your own Apple HomeKit Accessories to monitor air quality data using BleuIO

In this tutorial, we’ll walk you through the process of creating your own Apple HomeKit accessory that monitor and manage air quality data from a BLE device, specifically the HibouAir air quality monitoring device. By the end of this tutorial, you’ll have a functional BLE application that integrates with Apple’s HomeKit, demonstrating how easily you can develop BLE applications with the BleuIO dongle.

Overview of the Project

In this project, our goal is to create a BLE application that communicates with the HibouAir device, which provides air quality data. The application will:

  1. Connect to a BleuIO USB dongle to communicate with BLE devices.
  2. Scan for the HibouAir device using AT commands.
  3. Decode the air quality data from the HibouAir device.
  4. Integrate with HomeKit to display and manage the data in a smart home environment.
  5. Update the accessory information and continuously monitor the air quality data.

What is HomeKit?

HomeKit is Apple’s framework for home automation that allows users to control smart home devices using their Apple devices. With HomeKit, you can control a wide range of devices like lights, thermostats, locks, and sensors through the Apple Home app, Siri voice commands, and other Apple devices.

The key features of HomeKit include:

  • Secure Communication: HomeKit uses end-to-end encryption to ensure that data transmitted between your devices and the Home app remains private and secure.
  • Integration with Siri: HomeKit-enabled devices can be controlled using Siri voice commands, enabling hands-free control of your smart home.
  • Automation: Users can create automated routines and scenes that trigger actions based on time, location, or device status. For example, you can set up a “Good Night” scene that turns off the lights and locks the door when you say goodnight to Siri.

What is HAP-NodeJS?

HAP-NodeJS is an open-source implementation of the HomeKit Accessory Protocol (HAP) written in Node.js. It allows developers to create HomeKit-compatible accessories and bridge devices that can be controlled through Apple’s HomeKit ecosystem.

Devices Required

To follow this tutorial, you will need:

  1. BleuIO USB Dongle: A Bluetooth Low Energy USB dongle used to interface with BLE devices.
  2. HibouAir Device: A BLE air quality monitoring device that provides air quality metrics such as temperature, CO2 levels, humidity, and light levels.
  3. A Computer: Running Windows, macOS, or Linux ,  Raspberry Pi or any other platform that can run Node.js.

Connecting to BleuIO

To connect to the BleuIO dongle, we’ll use Node.js and the serialport package to communicate with the BLE device. The BleuIO dongle interfaces with your computer over a serial port, which allows you to send AT commands and receive data from BLE devices.

Decoding the Data

Once we receive the data from the HibouAir device, we need to decode it. The data is encoded in a specific format that we will parse and extract the relevant air quality metrics. We use a function to decode the advertisement data, which includes temperature, CO2 levels, humidity, and light levels.

Setting Up HomeKit Environment Data

We will use the hap-nodejs library to integrate our application with HomeKit. This will allow us to create HomeKit accessories that represent our air quality metrics. We set up services for temperature, CO2 levels, humidity, and light, and update these services with real-time data from the HibouAir device.

Running the Script

Here’s a step-by-step guide on how to set up and run the script:

  1. Install Required Packages
    First, make sure you have Node.js installed on your computer. Then, install the required npm packages by running
    npm install hap-nodejs serialport
  2. Create the Script
    Save the following code as hibouair.js or clone it from https://github.com/smart-sensor-devices-ab/bleuio-hibouair-homekit-integration
const hap = require('hap-nodejs');
const { SerialPort } = require('serialport');

const Accessory = hap.Accessory;
const Characteristic = hap.Characteristic;
const CharacteristicEventTypes = hap.CharacteristicEventTypes;
const Service = hap.Service;

// Get the device ID from the command-line arguments
const deviceId = process.argv[2];

if (!deviceId) {
  console.error(
    'Device ID not present. Please provide the device ID as follows:'
  );
  console.error('node hibouair.js <device_id>');
  process.exit(1);
}

// Define the manufacturer name you're looking for
const targetManufacturer = 'Smart Sensor Devices';

// Buffers to hold the incoming data
let buffer = '';
let scanningDetected = false;
let responseFound = false;
let port; // Variable to hold the SerialPort instance

// Initialize HomeKit accessories globally
let temperature, co2, humidity, light;

async function connectAndSendCommands() {
  try {
    // Get a list of all serial ports
    const ports = await SerialPort.list();

    // Find the port with the specified manufacturer
    const targetPort = ports.find(
      (port) => port.manufacturer === targetManufacturer
    );

    if (!targetPort) {
      console.log(`No port found with manufacturer: ${targetManufacturer}`);
      return;
    }

    // Log the selected port
    console.log(`Connecting to port: ${targetPort.path}`);

    // Create a new SerialPort instance for the selected port
    port = new SerialPort({
      path: targetPort.path,
      baudRate: 9600, // Adjust the baud rate as needed
    });

    // Event handler for when the port opens
    port.on('open', () => {
      console.log(
        `Port ${targetPort.path} is open and ready for communication.`
      );

      // Write the initial command
      port.write('AT+CENTRAL\r\n', (err) => {
        if (err) {
          console.error('Error writing initial command:', err.message);
        } else {
          console.log('Initial command sent: AT+CENTRAL');
        }
      });

      // Start the periodic scanning for BLE data
      setInterval(() => {
        port.write(`AT+FINDSCANDATA=${deviceId}=5\r\n`, (err) => {
          if (err) {
            console.error('Error writing scan command:', err.message);
          } else {
            console.log(`Scan command sent: AT+FINDSCANDATA=${deviceId}=5`);
          }
        });
      }, 20000); // 20000 milliseconds = 20 seconds
    });

    // Event handler for when data is received on the port
    port.on('data', (data) => {
      buffer += data.toString();
      processBuffer();
    });

    // Event handler for when there is an error
    port.on('error', (err) => {
      console.error('Error:', err.message);
      if (port) {
        port.close(() => {
          console.log('Port closed due to error.');
        });
      }
    });
  } catch (err) {
    console.error('Error listing or connecting to serial ports:', err);
    if (port) {
      port.close(() => {
        console.log('Port closed due to error.');
      });
    }
  }

  function processBuffer() {
    // Split the buffer into lines
    const lines = buffer.split('\r\n');

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i].trim();

      if (line === 'SCANNING...') {
        scanningDetected = true;
      } else if (line === 'SCAN COMPLETE') {
        scanningDetected = false;
      } else if (scanningDetected && line.length > 0) {
        // Extract the data from the line
        const dataMatch = line.match(/^\[.*?\] Device Data \[ADV\]: (.+)$/);
        if (dataMatch && dataMatch[1]) {
          const extractedData = dataMatch[1].trim();
          console.log('Extracted data:', extractedData);

          // Decode the data
          const decodedData = advDataDecode(extractedData);
          console.log('Decoded data:', decodedData);

          responseFound = true;
          buffer = ''; // Clear the buffer after finding the response

          if (!temperature || !co2 || !humidity || !light) {
            setupAccessory(decodedData); // Setup accessory if not already done
          } else {
            updateAccessory(decodedData); // Update accessory with decoded data
          }

          return;
        }
      }
    }

    // Keep the remaining buffer if no relevant line was found
    buffer = lines[lines.length - 1]; // Retain the last part of the buffer
  }

  // Function to decode the advertisement data
  function advDataDecode(adv) {
    let pos = adv.indexOf('5B0705');
    let dt = new Date();
    let currentTs =
      dt.getFullYear() +
      '/' +
      (dt.getMonth() + 1).toString().padStart(2, '0') +
      '/' +
      dt.getDate().toString().padStart(2, '0') +
      ' ' +
      dt.getHours().toString().padStart(2, '0') +
      ':' +
      dt.getMinutes().toString().padStart(2, '0') +
      ':' +
      dt.getSeconds().toString().padStart(2, '0');
    let tempHex = parseInt(
      '0x' +
        adv
          .substr(pos + 22, 4)
          .match(/../g)
          .reverse()
          .join('')
    );
    if (adv) dataShowing = true;
    if (tempHex > 1000) tempHex = (tempHex - (65535 + 1)) / 10;
    else tempHex = tempHex / 10;
    return {
      boardID: adv.substr(pos + 8, 6),
      type: adv.substr(pos + 6, 2),
      light: parseInt(
        '0x' +
          adv
            .substr(pos + 14, 4)
            .match(/../g)
            .reverse()
            .join('')
      ),
      pressure:
        parseInt(
          '0x' +
            adv
              .substr(pos + 18, 4)
              .match(/../g)
              .reverse()
              .join('')
        ) / 10,
      temp: tempHex,
      hum:
        parseInt(
          '0x' +
            adv
              .substr(pos + 26, 4)
              .match(/../g)
              .reverse()
              .join('')
        ) / 10,
      voc: parseInt(
        '0x' +
          adv
            .substr(pos + 30, 4)
            .match(/../g)
            .reverse()
            .join('')
      ),
      pm1:
        parseInt(
          '0x' +
            adv
              .substr(pos + 34, 4)
              .match(/../g)
              .reverse()
              .join('')
        ) / 10,
      pm25:
        parseInt(
          '0x' +
            adv
              .substr(pos + 38, 4)
              .match(/../g)
              .reverse()
              .join('')
        ) / 10,
      pm10:
        parseInt(
          '0x' +
            adv
              .substr(pos + 42, 4)
              .match(/../g)
              .reverse()
              .join('')
        ) / 10,
      co2: parseInt('0x' + adv.substr(pos + 46, 4)),
      vocType: parseInt('0x' + adv.substr(pos + 50, 2)),
      ts: currentTs,
    };
  }
}

// Function to setup HomeKit accessory
function setupAccessory(data) {
  const accessoryUuid = hap.uuid.generate('hap.hibouair.sensor');
  const accessory = new Accessory('HibouAir', accessoryUuid);

  // Create a function to initialize services
  function initializeService(
    serviceType,
    serviceName,
    initialValue,
    characteristicType
  ) {
    const service = new serviceType(serviceName);

    const characteristic = service.getCharacteristic(characteristicType);

    characteristic.on(CharacteristicEventTypes.GET, (callback) => {
      console.log(`Queried current ${serviceName}: ${initialValue}`);
      callback(undefined, initialValue);
    });

    accessory.addService(service);

    return {
      service,
      characteristic,
      initialValue,
    };
  }

  // Initialize temperature, CO2, humidity, and light services
  temperature = initializeService(
    Service.TemperatureSensor,
    'Temperature Sensor',
    data.temp,
    Characteristic.CurrentTemperature
  );

  co2 = initializeService(
    Service.CarbonDioxideSensor,
    'CO2 Sensor',
    data.co2,
    Characteristic.CarbonDioxideLevel
  );

  humidity = initializeService(
    Service.HumiditySensor,
    'Humidity Sensor',
    data.hum,
    Characteristic.CurrentRelativeHumidity
  );

  light = initializeService(
    Service.LightSensor,
    'Light Sensor',
    data.light,
    Characteristic.CurrentAmbientLightLevel
  );

  // Set accessory information
  accessory
    .getService(Service.AccessoryInformation)
    .setCharacteristic(Characteristic.Manufacturer, 'Smart Sensor Devices')
    .setCharacteristic(Characteristic.SerialNumber, deviceId);

  // Publish the accessory
  accessory.publish({
    username: '17:51:07:F4:BC:8B',
    pincode: '123-45-678',
    port: 47129,
    category: hap.Categories.SENSOR, // value here defines the symbol shown in the pairing screen
  });

  console.log('Accessory setup finished!');
}

// Function to update HomeKit accessory with new data
function updateAccessory(data) {
  temperature.initialValue = data.temp;
  co2.initialValue = data.co2;
  humidity.initialValue = data.hum;
  light.initialValue = data.light;

  console.log(`Updated current temperature: ${temperature.initialValue}`);
  console.log(`Updated current CO2 level: ${co2.initialValue}`);
  console.log(`Updated current Humidity level: ${humidity.initialValue}`);
  console.log(`Updated current light level: ${light.initialValue}`);

  // Update the characteristic values
  temperature.service.setCharacteristic(
    Characteristic.CurrentTemperature,
    temperature.initialValue
  );
  co2.service.setCharacteristic(
    Characteristic.CarbonDioxideLevel,
    co2.initialValue
  );
  humidity.service.setCharacteristic(
    Characteristic.CurrentRelativeHumidity,
    humidity.initialValue
  );
  light.service.setCharacteristic(
    Characteristic.CurrentAmbientLightLevel,
    light.initialValue
  );
}

// Call the function to connect and send commands
connectAndSendCommands();

Run the Script

Execute the script from your terminal by providing the device ID as an argument:

node hibouair.js 220069

This command will start the script, connect to the BleuIO dongle, scan for the HibouAir device, decode the data, and set up the HomeKit accessories with the real-time data from the device.

Output

This tutorial demonstrates how easy it is to develop BLE applications using BleuIO and integrate them with HomeKit. By following these steps, you can create real-time monitoring solutions for a variety of BLE-enabled devices, enhancing the functionality of your smart home environment.

Share this post on :

Master BLE Device Discovery with BleuIO : An Expert Guide for BLE Developers

Enhancing BLE Applications with BleuIO: Efficient Device Scanning and Data Retrieval

In the world of Bluetooth Low Energy (BLE) technology, discovering and connecting to nearby devices is a foundational feature. Whether you are developing a BLE-enabled smart home system, a fitness tracker, or an industrial IoT application, the ability to scan for nearby devices and retrieve data efficiently is crucial. The BleuIO USB dongle, with its user-friendly AT commands, simplifies this process significantly. This article explores how to utilize the scanning features of BleuIO to enhance your BLE applications.

Why Efficient Device Scanning is Essential

Efficient scanning for BLE devices is vital for several reasons:

  1. Device Discovery: Quickly identifying and connecting to nearby devices is crucial for seamless user experiences in applications such as smart home systems, wearables, and more.
  2. Data Retrieval: Scanning allows you to gather advertising and response data from nearby BLE devices, which can be used for various purposes, from device identification to obtaining sensor readings.
  3. Power Management: Optimizing scan parameters helps conserve battery life, which is particularly important for portable and battery-operated devices.

How BleuIO Can Be Helpful

The BleuIO USB dongle offers a range of AT commands that make BLE development straightforward and efficient. Key among these are commands for scanning nearby devices and retrieving advertising data. Let’s dive into three essential commands: AT+GAPSCAN, AT+FINDSCANDATA, and AT+SCANTARGET.

Command: AT+GAPSCAN

The AT+GAPSCAN command initiates a Bluetooth device scan, either indefinitely or for a specified duration. This command is only accepted when the device is in the central role and not connected to any other device.

  • Usage:
  • AT+GAPSCAN starts an indefinite scan.
  • AT+GAPSCAN=seconds starts a scan for the specified number of seconds.
  • Example:
AT+GAPSCAN
SCANNING...

[01] Device: [1]30:63:C5:D0:B1:DE RSSI: -38

[02] Device: [0]D0:76:50:80:0A:98 RSSI: -75 (closebeacon.com)

[03] Device: [1]27:5D:B8:2E:96:B0 RSSI: -51

[04] Device: [1]5E:CE:CF:C5:20:BB RSSI: -84

SCAN COMPLETE

In this example, the AT+GAPSCAN command scans for nearby BLE devices, displaying their addresses and signal strengths (RSSI).

Practical Applications of AT+GAPSCAN

  1. Smart Home Systems: Automatically discover and list all BLE-enabled devices in your home, such as smart lights, locks, and thermostats.
  2. Wearable Devices: Quickly identify nearby fitness trackers or health monitors for data synchronization.
  3. Retail Environments: Scan for BLE beacons that provide location-based advertisements or information.

Command: AT+FINDSCANDATA

The AT+FINDSCANDATA command scans for advertising and response data containing specific search parameters. This scan can run indefinitely or for a set duration and is particularly useful for filtering devices based on their advertised data.

  • Usage:
  • AT+FINDSCANDATA=search_params starts an indefinite scan for devices containing the specified search parameters.
  • AT+FINDSCANDATA=search_params=seconds scans for the specified duration.
  • Example:
AT+FINDSCANDATA=FF5
SCANNING...

[00:D4:2E:CD:72:23] Device Data [ADV]: 02010618FF5B00110101010101010101011405326845343864353466757675

[D7:D3:AA:00:B5:24] Device Data [ADV]: 02010618FF540930430924302903049320943094F90890548359049E495432

SCAN COMPLETE

In this example, the AT+FINDSCANDATA command scans for devices advertising data that contains the string “FF5”.

Practical Applications of AT+FINDSCANDATA

  1. Custom Applications: Filter and find specific BLE devices in environments with many BLE signals.
  2. Targeted Marketing: Identify BLE beacons with specific advertising data for targeted advertising campaigns.
  3. Industrial Monitoring: Locate and interact with BLE sensors that provide specific types of data.

Command: AT+SCANTARGET

The AT+SCANTARGET command scans for advertising and response data from specific devices. You can scan for one or multiple devices, and the scan continues indefinitely unless a timer is set.

  • Usage:
  • AT+SCANTARGET=[addr_type]slave_address starts an indefinite scan for the specified device.
  • AT+SCANTARGET=[addr_type]slave_address=seconds scans for the specified device for the given duration.
  • Multiple devices can be scanned by separating addresses with a semicolon (;).
  • Example:
AT+SCANTARGET=[0]00:00:00:00:00:01
SCANNING...

[00:00:00:00:00:01] Device Data [ADV]: DataXYZ

[00:00:00:00:00:01] Device Data [RESP]: DataXYZ

In this example, the AT+SCANTARGET command scans for advertising and response data from the device with address 00:00:00:00:00:01.

Practical Applications of AT+SCANTARGET

  1. Device Tracking: Continuously monitor specific devices for location and status updates.
  2. Data Collection: Retrieve advertising and response data from specific BLE sensors in a targeted manner.
  3. Security Systems: Monitor specific BLE-enabled security devices for activity and alerts.


Testing your BLE application

Testing is critical phases in the development of BLE applications. The scanning features of the BleuIO USB dongle, particularly the AT+GAPSCAN, AT+FINDSCANDATA, and AT+SCANTARGET commands, make these tasks easier and more effective for BLE developers.

During the testing phase, developers need to verify that their BLE applications can reliably discover and interact with nearby devices. The AT+GAPSCAN command allows developers to initiate comprehensive scans of the BLE environment, quickly identifying all nearby devices along with their signal strengths (RSSI). This functionality is essential for:

Range Testing: Evaluating the effective communication range of the application, which is crucial for applications requiring long-distance connectivity, such as smart home systems or industrial IoT.

Compatibility Testing: Ensuring the application can detect and communicate with a wide range of BLE devices, regardless of manufacturer or model.

Performance Testing: Assessing how well the application performs in environments with multiple BLE devices, including signal interference and response times.

The scanning features of the BleuIO USB dongle are indispensable tools for BLE developers, especially during the testing and prototyping phases. Commands like AT+GAPSCAN, AT+FINDSCANDATA, and AT+SCANTARGET not only streamline the discovery and interaction with nearby devices but also enhance the efficiency and effectiveness of the development process. With these powerful scanning capabilities, developers can ensure their BLE applications are robust, reliable, and ready for real-world use.

Share this post on :

Optimize Your BLE Connectivity using BleuIO’s Connection Scan Parameters

In Bluetooth Low Energy (BLE) technology, efficient device connectivity is crucial. Whether you’re developing a smart home solution, a wearable health monitor, or an industrial IoT application, managing how your device searches for and connects to others can significantly impact its performance. This is where the BleuIO USB dongle comes in, offering an array of intuitive AT commands to streamline BLE application development. One such command, AT+CONNSCANPARAM, is particularly valuable for fine-tuning connection parameters. This article explores why this feature is essential, how it can be beneficial, and practical applications in the real world.

Why Connection Parameters Matter

Connection parameters in BLE devices dictate how often and how long a device scans for other devices. Proper configuration of these parameters is vital for several reasons:

  1. Power Efficiency: BLE devices are often battery-powered. Efficient scanning helps conserve battery life, extending the operational period of the device.
  2. Performance: The frequency and duration of scans can affect how quickly and reliably devices discover each other and establish connections.
  3. Scalability: In environments with multiple BLE devices, optimized scanning reduces interference and improves overall communication quality.

How BleuIO Can Be Helpful

The BleuIO USB dongle simplifies BLE development with its user-friendly AT commands. The AT+CONNSCANPARAM command is particularly powerful, allowing developers to set and query the scan interval and scan window parameters, thus optimizing the device’s connectivity according to specific application needs. This flexibility is invaluable for creating efficient, responsive, and reliable BLE applications.

Introducing the AT+CONNSCANPARAM Command

The AT+CONNSCANPARAM command is designed to set or query the connection scan window and interval. These parameters are crucial for managing how the BLE device initiates scans and how long it scans for during each interval.

  • Scan Interval: The time between consecutive scans.
  • Scan Window: The duration of each scan within the interval.

The command ensures the scan window is always equal to or smaller than the scan interval. Values can be set in steps of 0.625 milliseconds (ms), with the interval ranging from 2.5 ms to 10,240 ms.

Practical Applications in Real Life

Let’s explore how AT+CONNSCANPARAM can be applied in various real-world scenarios:

  1. Wearable Health Monitors: In wearable devices like fitness trackers or heart rate monitors, battery life is a critical factor. By adjusting the scan interval and window, developers can optimize these devices to scan less frequently but for longer periods, conserving battery while maintaining reliable data transmission. AT+CONNSCANPARAM=800=400 This command sets the scan interval to 500 ms and the scan window to 250 ms, balancing power efficiency with performance.
  2. Smart Home Devices: Devices such as smart locks or light bulbs need to be responsive to user commands. A shorter scan interval and longer scan window can enhance responsiveness. AT+CONNSCANPARAM=200=150 Here, the scan interval is 125 ms, and the scan window is 93.75 ms, ensuring quick response times while maintaining reasonable power consumption.
  3. Industrial IoT: In environments with numerous BLE devices, such as a factory floor, optimizing scan parameters can reduce interference and improve connectivity stability. AT+CONNSCANPARAM=400=200 This sets the scan interval to 250 ms and the scan window to 125 ms, ensuring efficient and stable communication amidst many devices.

Setting and Querying Connection Scan Parameters

To set the connection scan parameters, use the command in the following format:

AT+CONNSCANPARAM=scan_intv_ms=scan_win_ms

For example:

AT+CONNSCANPARAM=200=100
OK

This sets the scan interval to 125 ms (200 * 0.625 ms) and the scan window to 62.5 ms (100 * 0.625 ms). The device responds with OK indicating success.

To query the current parameters, simply use:

AT+CONNSCANPARAM

The device will return:

Connection Scan Interval = 320
Connection Scan Window = 160

This means the scan interval is 200 ms (320 * 0.625 ms) and the scan window is 100 ms (160 * 0.625 ms).

The AT+CONNSCANPARAM command on the BleuIO USB dongle provides developers with a powerful tool to optimize BLE connectivity for various applications. By understanding and leveraging this command, you can enhance the power efficiency, performance, and scalability of your BLE devices, making them more reliable and effective in real-world scenarios.

Unlock the full potential of your BLE projects with BleuIO. Get your dongle today and start creating smarter, more efficient BLE applications.

Share this post on :

Introducing BleuIO Firmware v2.7.4: Enhanced Scanning Capabilities

We are thrilled to announce the release of the latest firmware update for our popular Bluetooth Low Energy USB dongle, BleuIO. With version 2.7.4, we continue our commitment to providing the most versatile and user-friendly BLE solutions for developers. This update brings a host of new features designed to simplify and enhance your BLE application development process.

What’s New in Firmware v2.7.4?

Enhanced Scanning Functionality

In our ongoing effort to provide comprehensive BLE solutions, we’ve added several new commands that significantly improve the scanning capabilities of the BleuIO dongle. These updates allow developers to have more control over their BLE environment and extract more detailed information from nearby devices.

1. Device Name and Manufacturer Specific ID in Scan Results

The new firmware includes commands that enable the display of device names and manufacturer-specific IDs (Company IDs) in the advertising data or scan response. This feature is applicable to all modes of scans, including AT+GAPSCAN, AT+FINDSCANDATA, and AT+SCANTARGET. With these enhancements, identifying and differentiating between devices becomes more straightforward and efficient.

ATASSN: Toggle showing device names on or off in scans using AT+FINDSCANDATA and AT+SCANTARGET.

ATASSM: Toggle showing manufacturer-specific IDs on or off in scans using AT+GAPSCAN, AT+FINDSCANDATA, and AT+SCANTARGET.

2. Customizable Scan Interval and Scan Window

To provide more flexibility during connections, we’ve introduced a command to set the scan interval and scan window parameters. This feature ensures that you can fine-tune your scanning behavior to match the specific needs of your application, optimizing both power consumption and performance.

AT+CONNSCANPARAM: Set the scan interval and scan window used in connections.

3. Comprehensive Scan Parameter Configuration

We’ve also added a command to configure various scan parameters, allowing you to tailor the scanning process to your precise requirements. This includes settings for scan mode, scan type, scan interval, scan window, and filter duplicates, applicable across all scanning commands.

AT+SCANPARAM: Set scan parameters for AT+GAPSCAN, AT+FINDSCANDATA, and AT+SCANTARGET.

Benefits of the New Features

These enhancements are designed to offer several key benefits:

Improved Device Identification: Easily identify devices by their names and manufacturer IDs, making it simpler to manage and interact with multiple BLE devices.

Customizable Performance: Adjust scan intervals and windows to optimize for either speed or power efficiency based on your application’s needs.

Greater Control: Fine-tune scanning parameters to ensure you capture the most relevant data, minimizing noise and maximizing the efficiency of your BLE operations.

How to Update

Updating your BleuIO dongle to firmware version 2.7.4 is straightforward. Simply follow the instructions provided in our firmware update guide.

Get Started with the New Commands

To help you get started with the new features, we’ve updated our AT command reference guide with detailed explanations and examples for each of the new commands.

Share this post on :

Integrating BleuIO with Adafruit Feather RP2040 for Seamless BLE Applications (noise sensor) : Part 4

Introduction

This example is going to showcase how to connect a PDM MEMS Microphone to a Adafruit Feather RP2040, together with a BlueIO to create a background noise sensor that measures and advertisises the current sound level in decibel (dB).
This example is very similar to Integrating BleuIO with Adafruit Feather RP2040 for Seamless BLE Applications Part 2 but instead of reading sensor data over SPI every few seconds, we’re using the arduino PDM interface to continuously fill a buffer with data then everytime the buffer is full we’re going to translate the data into the current sound level in dB.
The buffer size of 8000 bytes (2 bytes per sample) and the sample rate of 16kHz means we record 250ms each time we fill the buffer.

Requirements

Connecting PDM Microphone.

  • Connect four wires from the PDM Microphone (3V, GND, DAT, CLK) to the following pins on the Feather Board:
  • 3V to 3.3V to power the device, then GND to GND.

  • And CLK to SCL, and DAT to SDA.

Running the example

  • Make sure the BleuIO Dongle is connected to the Feather RP2040 Board.
  • Connect the Feather RP2040 Board to your computer using the USB cable.
  • Make sure the Feather RP2040 Board is selected as well as the correct COM port in the drop-down menu.
  • (Optional) Change the frequency the advertising message is updated with the dB value, in the code
    // How often we update the advertising message (in seconds) #define READ_UPDATE_FREQUENCY 1
  • Click the Upload button.
  • Done! The dongle should now be advertising the sensor values. (If you just plugged in the Feather it may take about 10 seconds before advertising starts as the BleuIO bootloader opens and closes)
  • (Optional) Open Serial Monitor. You can open the Serial Monitor from the menu: Tools>Serial Monitor
    You should now see the output from the project.

Scanning the results

To see the results you can use any BLE scanner app.
Here we use nRF Connect:


The data in the red box is our sensor values:
0x0032

When we parse the hex into decimal values we get:
0x0032 = 50 dB

Share this post on :

BleuIO Firmware Update v2.7.3: Enhancing Connectivity and Usability

The latest firmware update for BleuIO, version 2.7.3, brings a suite of new functionalities and commands designed to enhance the performance and user experience of this Bluetooth Low Energy (BLE) USB dongle. With continuous firmware updates, BleuIO ensures that users can develop BLE applications quickly and efficiently. Here’s a detailed look at what the new update offers:

New Functionalities in v2.7.3

  1. Bonded Device Connectivity Improvement:
    • A new command has been introduced to scan for and connect to bonded devices, even if these devices are using a Private Random Resolvable Address. This improvement ensures that devices can maintain secure connections and improve overall reliability in various use cases.
  2. Toggle Resolved Addresses in Scan Results:
    • Users now have the option to toggle on or off the display of resolved addresses in scan results. This feature can be activated when using the AT+GAPSCAN command, providing greater control over the information displayed during device scans.
  3. Index-based Connection Command:
    • The AT+GAPCONNECT command has been enhanced to allow the use of an index from scan results obtained via the AT+GAPSCAN command. This simplifies the connection process by removing the need to input the full MAC address.
  4. Verbose Mode Index Display:
    • A new command allows users to toggle on or off the display of indexes from AT+GAPSCAN scan results in verbose mode. This feature is particularly useful for developers who need detailed scan information for debugging and development purposes.

New Commands Added

  1. AT+CONNECTBOND:
    • This command facilitates connection with already bonded devices, even if these devices are advertising using a Private Random Resolvable Address. It streamlines the reconnection process and enhances device management.
  2. ATSRA:
    • This command enables the display of resolved addresses in the scan results. It is a useful tool for users who need to view detailed addressing information during device scans.
  3. ATSIV:
    • This command allows users to show indexes in the verbose mode scan results. It provides an additional layer of information that can be crucial for in-depth analysis and debugging.

The v2.7.3 firmware update for BleuIO brings significant enhancements that improve both connectivity and usability. By adding new commands and functionalities, BleuIO continues to support developers in creating robust and efficient BLE applications. Whether you’re working on a new project or maintaining an existing application, these updates offer valuable tools and improvements to streamline your development process.

The new firmware can be downloaded from our getting started guide.

Share this post on :

Building a BLE Application with ReactJS and BleuIO

In this tutorial, we’ll explore how to create a Bluetooth Low Energy (BLE) application using ReactJS and the BleuIO BLE USB dongle. BleuIO is a versatile BLE device that makes developing BLE applications fast and easy with its user-friendly AT commands.

Introduction

Bluetooth Low Energy (BLE) technology is widely used for short-range communication, particularly in IoT applications. BleuIO, with its easy-to-use AT commands, simplifies the process of integrating BLE functionality into your applications. In this tutorial, we’ll demonstrate how to create a BLE application using ReactJS. Specifically, we will show you how to scan for nearby BLE devices for three seconds and display the results on the screen, highlighting the capabilities of BleuIO.

Prerequisites

Before we start, make sure you have the following:

  • A BleuIO USB dongle
  • A computer with a Chromium-based browser (like Chrome or Edge)
  • Node.js and npm installed
  • Basic knowledge of ReactJS

Setting Up the Project

First, let’s create a new React project. If you haven’t already installed create-react-app, you can do so with the following command:

npx create-react-app ble-react-app
cd ble-react-app
npm start

This will create a new React application and start the development server.

Creating the Serial Port Component

We’ll create a component to handle the serial port communication with the BleuIO dongle. Create a new file called SerialPortComponent.js in the src directory and add the following code:

import React, { useState, useEffect } from 'react';

const SerialPortComponent = () => {
const [port, setPort] = useState(null);
const [output, setOutput] = useState('');
const [reader, setReader] = useState(null);
const [writer, setWriter] = useState(null);

const connectToSerialPort = async () => {
try {
// Request a port and open a connection.
const selectedPort = await navigator.serial.requestPort();
await selectedPort.open({ baudRate: 9600 });
setPort(selectedPort);

const textDecoder = new TextDecoderStream();
const readableStreamClosed = selectedPort.readable.pipeTo(
textDecoder.writable
);
const reader = textDecoder.readable.getReader();
setReader(reader);

const textEncoder = new TextEncoderStream();
const writableStreamClosed = textEncoder.readable.pipeTo(
selectedPort.writable
);
const writer = textEncoder.writable.getWriter();
setWriter(writer);

// Read data from the serial port.
readSerialData(reader);
} catch (error) {
console.error('There was an error opening the serial port:', error);
}
};

const readSerialData = async (reader) => {
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
// Allow the serial port to be closed later.
reader.releaseLock();
break;
}
// Convert the received data to a string and update the state.
setOutput((prevOutput) => prevOutput + value);
}
} catch (error) {
console.error('Error reading from the serial port:', error);
}
};

const writeToSerialPort = async () => {
setOutput('');
try {
if (writer) {
// Send AT+CENTRAL command
await writer.write('AT+CENTRAL\r');
setOutput((prevOutput) => prevOutput + 'AT+CENTRAL\r\n');

// Wait for a short while to ensure the command is processed
await new Promise((resolve) => setTimeout(resolve, 500));

// Send AT+GAPSCAN=3 command
await writer.write('AT+GAPSCAN=3\r');
setOutput((prevOutput) => prevOutput + 'AT+GAPSCAN=3\r\n');

// Wait for scan to complete and read response
await new Promise((resolve) => setTimeout(resolve, 3000));

// Read and process data from the serial port
let scanData = '';
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
scanData += value;
}
setOutput((prevOutput) => prevOutput + scanData);
} else {
console.error('Writer not available');
}
} catch (error) {
console.error('Error writing to the serial port:', error);
}
};

useEffect(() => {
return () => {
// Cleanup function to close port when component unmounts
if (port) {
port.close();
}
if (reader) {
reader.releaseLock();
}
if (writer) {
writer.releaseLock();
}
};
}, [port, reader, writer]);

return (
<div className="mt-5">
<button
className="btn btn-success me-2"
onClick={connectToSerialPort}
disabled={!!port}
>
Connect to BleuIO
</button>
<button
className="btn btn-warning me-2"
onClick={writeToSerialPort}
disabled={!writer}
>
Scan for nearby BLE devices for 3 seconds
</button>

{output && (
<div>
<h3>Response from the BleuIO:</h3> <pre>{output}</pre>
</div>
)}
</div>
);
};

export default SerialPortComponent;

Explanation of the Code

  1. Connecting to the Serial Port: The connectToSerialPort function requests access to the serial port and opens a connection. It initializes the text encoder and decoder streams for reading and writing data.
  2. Reading Serial Data: The readSerialData function reads data from the serial port continuously and updates the output state with the received data.
  3. Writing to the Serial Port: The writeToSerialPort function sends AT commands to the serial port. It first sends the AT+CENTRAL command to put the device in central mode, then sends the AT+GAPSCAN=3 command to scan for nearby BLE devices for 3 seconds. It reads and displays the response from the serial port after the scan completes.
  4. Cleanup: The useEffect hook ensures that the serial port is properly closed and resources are released when the component is unmounted.

Using the Component in Your App

Update your App.js to include the new SerialPortComponent.

// src/App.js
import React from 'react';
import SerialPortComponent from './SerialPortComponent';

function App() {
return (
<div className="App">
<header className="App-header">
<h1>BLE Application with React and BleuIO</h1>
<SerialPortComponent />
</header>
</div>
);
}

export default App;

Running the Application

Make sure your BleuIO USB dongle is connected to your computer. Start your React application:

npm start

Open your browser and navigate to http://localhost:3000. You should see the application with two buttons: “Connect to BleuIO” and “Scan for nearby BLE devices for 3 seconds“.

  • Connect to BleuIO: Click this button to connect to the BleuIO USB dongle. The browser will prompt you to select the serial port.
  • Scan for nearby BLE devices for 3 seconds: After connecting, click this button to send the AT+CENTRAL and AT+GAPSCAN=3 commands to the BleuIO dongle. The output area will display the response from the device.

Output

In this tutorial, we’ve demonstrated a basic usage of BleuIO AT commands by creating a BLE application using ReactJS and the BleuIO USB dongle. By leveraging the Web Serial API and the straightforward AT commands provided by BleuIO, you can quickly develop BLE applications that run on any platform. You can expand on this example to develop your own applications using BleuIO’s comprehensive set of AT commands. Read more about the AT commands in our documentation.

BleuIO simplifies BLE development and, combined with the popularity and versatility of ReactJS, allows developers to create powerful and cross-platform BLE applications with ease. Whether you’re building IoT devices, wearable tech, or any BLE-enabled application, BleuIO is a reliable and efficient choice.

Share this post on :

BleuIO Firmware Update 2.7.2: Enhanced Security and Stability

The BleuIO Bluetooth Low Energy (BLE) USB dongle continues to set the standard for BLE application development with its latest firmware update, version 2.7.2. This update brings significant enhancements, focusing on security features and critical bug fixes, making it an essential upgrade for developers and users of BleuIO.

Key Enhancements in Firmware 2.7.2

Enhanced Security with Authentication and Encryption Permissions

One of the most notable additions in this update is the introduction of Authentication and Encryption Permission support for Custom Service attributes. This feature is a major step forward in ensuring secure BLE communications. The permissions framework allows the server (BleuIO) to determine the client’s access level to characteristic or descriptor values based on the need for an authenticated and/or encrypted connection. This means that sensitive data can now be protected more robustly, ensuring that only authorized clients can read from or write to specific attributes.

Bug Fixes and Stability Improvements

The 2.7.2 firmware update also addresses several bugs that were affecting the reliability and performance of the BleuIO dongle. Here are the key fixes:

  1. AT+GETBOND Command Bug Fixes:
    • Incorrect MAC Addresses: Previously, the AT+GETBOND command occasionally returned incorrect MAC addresses. This issue has now been resolved, ensuring accurate reporting of bonded device addresses.
    • Removal of Address Type: The address type part of the MAC address, which was always returned as PUBLIC_ADDRESS (0) and not stored with the bonding information, has been removed. This simplification helps in reducing confusion and potential errors in handling bonded device information.
  2. AT+GAPSCAN Command Stability:
    • The command AT+GAPSCAN= with an empty argument previously caused the device to reset unexpectedly. This bug has been fixed, ensuring stable and predictable behavior when scanning for devices.
  3. Connection Initiation Fixes:
    • The update resolves issues where attempting to initiate a connection using AT+GAPCONNECT while also advertising led to unpredictable behavior, such as being unable to connect or scan properly. This fix enhances the overall stability and reliability of establishing BLE connections.

For developers and users of the BleuIO dongle, updating to firmware version 2.7.2 is highly recommended. The new security features ensure that your BLE applications can enforce stringent access controls, protecting sensitive data. The bug fixes improve the overall functionality and reliability of the device, reducing the likelihood of encountering errors during development and deployment.

For more detailed information and to download the latest firmware, visit the BleuIO getting started guide.

Share this post on :

Integrating BleuIO with Adafruit Feather RP2040 for Seamless BLE Applications Part 3 (secure connection)

Introduction

Building on the steps in our previous post Integrating BleuIO with Adafruit Feather RP2040 for Seamless BLE Applications Part 2 where we showed how to use the BleuIO to advertise sensor data, we are now going to put the data in a Custom Service. Additionally, we are going to protect the data by making it only available with a secure connection that can only be established by entering a 6-digit passkey.

This example is going to show you how to start protecting your data as well as how to set up and use a custom service.

Requirements

Running the example

Make sure the BleuIO Dongle is connected to the Feather RP2040 Board. Connect the Feather RP2040 Board to your computer using the USB cable.

Make sure the Feather RP2040 Board is selected as well as the correct COM port in the drop-down menu.

(Optional) Change the passkey used for the secure connection and/or the frequency the sensors are read, in the code

/* Requires 6 digits */
#define SECURE_CONN_PASSKEY "232425"
// How often we read the sensors and update the characteristics (in
seconds)
#define READ_UPDATE_FREQUENCY   5

Click the Upload button.

Done! The dongle should now be advertising the sensor values. (If you just plugged in the Feather it may take about 10 seconds before advertising starts as the BleuIO bootloader opens and closes)

(Optional) Open Serial Monitor. You can open the Serial Monitor from the menu:

Tools>Serial Monitor

You should now see the output from the project.

Getting the data

To get the results you can use any BLE scanner app. Here we use nRF Connect:

Find the device that advertise as BleuIO Arduino Example and connect.

You will be prompted to pair.

And then to enter the passkey.
Enter the passkey/pin (default: 232425) and continue.

Go to the service with the UUID: ee6ec068-7447-4045-9fd0-593f3ba3c2ee Notice that you are now bonded.

The service has 5 characteristics, one for each of the sensor values:

1. Lux
2. Pressure
3. Temperature
4. Humidity
5. Gas resistance

Read and/or enable notification for each characteristic to see the data.
The Characteristic User Description Descriptor of each characteristic can be read to show what value it holds.

Like in the previous example, when we parse the hex into decimal values we get:

Lux: 0x0068 = 104 uW/cm2
Pressure: 0x03F8 = 1016 hPa
Temperature: 0x0017 = 23 Celcius
Humidity: 0x0017 = 23 %Rh
Gas Resistance: 0x0041 = 65 KOhms

If not bonded, the values will always show 00-00.

Share this post on :

Developing BLE Applications with BleuIO and Rust

BleuIO is a versatile Bluetooth Low Energy (BLE) USB dongle designed to simplify the development of BLE applications. With its support for AT commands and seamless integration with Rust programming language, BleuIO offers developers a straightforward and efficient way to create BLE applications. In this tutorial, we will explore how to use BleuIO and Rust to develop BLE applications easily.

About Rust Programming Language:

Rust is a modern, systems programming language that focuses on safety, performance, and concurrency. Developed by Mozilla, Rust has gained popularity for its unique features and advantages, making it an excellent choice for various application domains, including system programming, web development, and embedded systems.

Prerequisites:

Setting Up BleuIO:

  1. Connect BleuIO Dongle:
    • Connect the BleuIO dongle to an available USB port on your computer.
  2. Identify Serial Port:
    • Identify the serial port associated with BleuIO. For example, On macOS and Linux, it may look like /dev/cu.usbmodem4048FDE52DAF1. On windows it looks like COM6

Installing Rust and Cargo:

  • Windows:
    • Download and install the Rust compiler (including Cargo) from the official website: Rustup.
    • Follow the installation instructions provided on the website.
  • Mac/Linux:
    • Open a terminal and run the following command to install Rust and Cargo:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Follow the on-screen instructions to complete the installation.

Creating a Cargo Project:

  • Open Terminal/Command Prompt:
    • Windows: Open Command Prompt or PowerShell.
    • Mac/Linux: Open Terminal.
  • Navigate to Project Directory:
cd /path/to/projects
  • Create a New Cargo Project:
cargo new BleuIO

This will create a new directory named “BleuIO” containing the project files.

  • Navigate into the Project Directory:
cd BleuIO

Writing BLE Application Code:

  • Open src/main.rs in Your Code Editor:
    • Replace the default Rust code with the BLE application code. Make sure to replace the port_name with your connected BleuIO port.
  • Implement BLE Application Logic:
    • Write Rust code to interact with BleuIO using AT commands.
use std::io::{self, Write};
use std::thread::sleep;
use std::time::Duration;
use serialport;

fn main() -> io::Result<()> {
    // Open the serial port
    let port_name = "/dev/cu.usbmodem4048FDE52DAF1";
    let mut port = serialport::new(port_name, 9600)
        .timeout(Duration::from_secs(5)) // Adjust timeout value here (5 seconds in this example)
        .open()
        .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    // Write "AT+CENTRAL" to set the BleuIO dongle to centrla role
    let data_central = b"AT+CENTRAL\r\n";
    port.write_all(data_central).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    // Wait for 500 milliseconds
    sleep(Duration::from_millis(5));

    // Write "AT+GAPSCAN=3" to scan for nearby BLE devices for 3 seconds
    let data_gapscan = b"AT+GAPSCAN=3\r\n";
    port.write_all(data_gapscan).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

    // Read response from the BleuIO dongle until no more data is available
    let mut response = String::new();
    loop {
        let mut buffer: [u8; 128] = [0; 128];
        let bytes_read = port.read(&mut buffer).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;

        // Check if no more data is available
        if bytes_read == 0 {
            break;
        }

        // Convert bytes to string and append to the response
        let chunk = String::from_utf8_lossy(&buffer[..bytes_read]);
        response.push_str(&chunk);

        // Print the current chunk of response
        print!("{}", chunk);
    }

    // Drop the port to close it
    drop(port);

    Ok(())
}

Building and Running the Project:

  • Build the Project:
cargo build
  • Run the Project:
cargo run

Output

In this tutorial, we’ve demonstrated how to develop a simple BLE applications using BleuIO and Rust that puts the BleuIO in central role and scans for nearby BLE devices for 3 seconds. Finally shows the list on the screen. By using BleuIO’s support for AT commands and Rust’s simplicity, developers can create BLE applications effortlessly. Start exploring the possibilities with BleuIO and Rust today!

Share this post on :