npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@modum-io/modblue

v12.0.4

Published

BLE module using dbus or hci.

Downloads

3

Readme

ModBlue

Trying to make the world better place by improving the bluetooth experience one library at a time.

Getting started

Prerequisites

OS X

Linux

  • Give net_cap_raw to node

    This command may not work if you're using NVM or asdf!
    Make sure to give the actual node binary the permission

    sudo setcap cap_net_raw+eip $(eval readlink -f $(which node))
  • Stop/Disable the bluetooth service if you're planning to advertise with the hci bindings:

    Please note that this stops the dbus bindings from working properly!

    sudo systemctl stop bluetooth

    You can also disable it permanently:

    sudo systemctl disable bluetooth
Debian flavours
  •  sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev
Fedora and other RPM-based distros
  •  sudo yum install bluez bluez-libs bluez-libs-devel

Installation

Install the module from npm:

npm i -E @modum-io/modblue

Then install the peer depencies depending on which one(s) you want to use:

Usage

Create a new MODblue object to get started (all bindings have the same interface)

import { HciMODblue } from '@modum-io/modblue/hci'; // for hci bindings
// import { DbusMODblue } from '@modum-io/modblue/dbus'; // for dbus bindings

const modblue = new HciMODblue();    // or: new DbusMODblue()

Now you can scan & use one or multiple of the adapters:

const adapters = await modblue.getAdapters();
const adapter = adapters[0];

Scanning

Use an adapter to scan for devices in proximity:

const serviceUUIDs: string[] = [];        // Optional: Advertised service UUIDs, without dashes (-)
const allowDuplicates: boolean = true;    // Optional: Allow duplicate 'discover' events for the same device

await adapter.startScanning(serviceUUIDs, allowDuplicates);

Now you can either wait for a few seconds to scan and then get all the scanned peripherals

const peripherals = await adapter.getScannedPeripherals();

or you can attach an event to trigger each time a new peripheral is discovered (or more often if allowDuplicates is true):

adapter.on('discover', (peripheral) => console.log('Discovered', peripheral.address));

Once discovered you can connect to a peripheral and grab it's GATT to discover services and characteristics:

await peripheral.connect();

// Setup GATT
const requestMtu = 517;    // Optional: Request a specific MTU
const gatt = await peripheral.setupGatt(requestMtu);

// Discover services
const services = await gatt.discoverServices();
const service = services[0];

// Discover characteristics
const characteristics = await service.discoverCharacteristics();
const characteristic = characteristics[0];

// Discover descriptors
const descriptors = await characteristic.discoverDescriptors();
const descriptor = descriptors[0];

// Read value
const buffer = await characteristic.read();
// or
const buffer = await descriptor.readValue();

// Write value
const withoutResponse: boolean = true;    // Tell the peripheral we don't need a response for this write

await characteristic.write(buffer, withoutResponse);
// or
await descriptor.writeValue(buffer);

Advertising

First you have to setup the local GATT and the services and characteristics you want to advertise:

import { GattServiceInput } from '@modum-io/modblue';

const maxMtu: number = 517;                             // Optional: Specify the maximum MTU that should be negotiated with connecting devices.
const gatt = await adapter.setupGatt(maxMtu);           // Setup our local GATT server

const deviceName: string = 'MODblue Testing';
const services: GattServiceInput[] = [
   {
      uuid: '48ee0000bf49460ca3d77ec7a512a4ce',          // UUID of the service (without dashes [-])
      characteristics: [
         {
            uuid: '48ee0001bf49460ca3d77ec7a512a4ce',    // UUID of the characteristic
            properties: ['read'],                        // Supported properties on the characteristic
            secure: [],                                  // Which of the supported properties are secured
            descriptors: [],                             // Descriptors on this characteristic
            value: Buffer.from('test', 'utf-8')          // The (constant) data that is returned for this characteristic
         },
      {
         uuid: '48ee0002bf49460ca3d77ec7a512a4ce',
         properties: ['read'],
         secure: [],
         descriptors: [],
         onRead: async (offset) => {
            // This function receives the offset at which to start reading
            if (offset === 0) {
               // Only do your computation when the first bytes are requested.
               // In case of subsequent reads (because of long data / small MTU) we want to return the same data as before, starting at the offset
               }

               // Returns a tuple containing: [error: number, data: Buffer] - Use 0 for the error on success.
               return [0, Buffer.from('other', 'utf-8').slice(offset)];
            }
         },
         {
            uuid: '48ee0003bf49460ca3d77ec7a512a4cd',
            properties: ['write', 'write-without-response'],
            secure: [],
            descriptors: [],
            onWrite: (offset, data, withoutResponse) => {
               // This function handles writing data to the characteristic
               console.log('writing', offset, data, withoutResponse);
            }
         }
      ]
   }
];
gatt.setData(deviceName, services);

To advertise services and characteristics use:

const deviceName: string = 'MODblue Testing';    // You can use a different advertising name then the name in the GATT
const advertisedServiceUUIDs: string[] = [];     // Optional: Advertise specific service UUIDs (without dashes [-])

await adapter.startAdvertising(deviceName, advertisedServiceUUIDs);

Tests

Adapters

This test will list all available adapters for all available bindings.

  1. Run test using

    node tests/adapters.js

Connect

This test will connect, discover services and characteristics, read a single characteristic value and disconnect. The test runs indefinitely and rotates between all specified devices.

  1. Run test using

    export BINDINGS="hci";
    export LOGGER_IDS="AA:AA:AA:AA:AA:AA|BB:BB:BB:BB:BB:BB";
    export SERVICE_ID="48ee0000bf49460ca3d77ec7a512a4cd";
    export CHARACTERISTIC_ID = "48ee000bbf49460ca3d77ec7a512a4cd";
    node tests/connect.js $BINDINGS $LOGGER_IDS $SERVICE_ID $CHARACTERISTIC_ID

Advertise

This test will advertise some services and characteristics under a specified name. The test runs indefinitely and waits for connections.

  1. Run test using

    export BINDINGS="hci";
    export ADVERTISE_NAME="MODblue Testing";
    node tests/advertise.js $BINDINGS "$ADVERTISE_NAME"