
Security News
OWASP 2025 Top 10 Adds Software Supply Chain Failures, Ranked Top Community Concern
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.
@sblendid/sblendid
Advanced tools
Bluetooth Low Energy for JavaScript
With Sblendid you can find and connect to Bluetooth Low Energy (BLE) devices (called peripherals) and interact with them. It is implemented in TypeScript and built on top of native code using the system's bluetooth APIs.
npm install @sblendid/sblendid @sblendid/adapter-node
Important development notice
Sblendid has not oficially been released yet. You can already install it, but this is a "silent launch" and supports macOS and Windows only thus far. I am currently working on Linux support and will publish version 1.0.0 once I have finished this and the documentation.
Sblendid will support Linux, macOS and Windows. In the future, Sblendid should support other platforms
including React Native and WebBluetooth. Hence, you have to install the @sblendid/adapter-node
package as a seperate dependency. Native modules for macOS and Windows are provided by
Timeular (thanks!)
As this is in an early stage, your feedback is very welcome, please don't hesitate to file issues.
With BLE you usually use the GATT protocol. This means you
connect to a peripheral, get one ore more services of that peripheral and read / write / subscribe to
values on these services. With Sblendid this works as follows:
import Sblendid from "@sblendid/sblendid";
(async () => {
const peripheral = await Sblendid.connect("My Peripheral");
const service = await peripheral.getService("uuid");
const value = await service.read("uuid");
await service.write("uuid", Buffer.from("value", "utf8"));
service.on("uuid", value => console.log(value));
// You need to power off your Bluetooth adapter or your Node process won't end
await Sblendid.powerOff();
})();
Timeouts
It is important to know that no function in this libary has a timeout.
Sblendid.connectwill scan indefinitely unless you make sure it doesn't. At some point in the future timeouts will be built in but it is not a scope of version 1.0.0
In the previous example, all values you read, write or get notified for are
Buffers. It might get weary to constantly convert
Buffers to the values you actually want to work on. For this, Sblendid introduces a
concept called converters.
import Sblendid from "@sblendid/sblendid";
// Converts buffers to another value and back. You can
// work with numbers, objects, classes or anything as
// long as you write appropriate decode and encode functions
const converters: {
myValue: {
uuid: "uuid",
decode: buffer => buffer.toString(),
encode: message => Buffer.from(message, "utf8")
},
otherValue: {
uuid: "anotherUuid",
decode: buffer => buffer.readUInt8(0),
encode: num => Buffer.from([num])
}
};
(async () => {
const peripheral = await Sblendid.connect("My Peripheral");
const service = await peripheral.getService("uuid", converters);
// value will be a string
const value = await service.read("myValue");
// you can pass a string
await service.write("myValue", "value");
// value will also be a string
service.on("myValue", value => console.log(value));
// values for "otherValue" will be numbers
const value2 = await service.read("otherValue");
await service.write("otherValue", 22);
service.on("otherValue", value => console.log(value));
// You need to power off your Bluetooth adapter or your Node process won't end
await Sblendid.powerOff();
})();
import Sblendid from "@sblendid/sblendid";
(async () => {
const sblendid = await Sblendid.powerOn();
sblendid.startScanning(peripheral => {
const { uuid, name, connectable, advertisement } = peripheral;
const { txPowerLevel, manufacturerData, serviceUUIDs } = advertisement;
console.log("Found Peripheral:");
console.log(uuid, name, connectable);
console.log(txPowerLevel, manufacturerData, serviceUUIDs);
});
// You need to power off your Bluetooth adapter or your Node process won't end
// Note the lower case "s", powerOff is a static and an instance method
await sblendid.powerOff();
})();
The callback in startScanning will receive an instance of Peripheral. See
There are several ways to find and connect to a peripheral.
You can use Sblendid.connect and pass either a
NameUUIDAddresscallback function returning a boolean, or a Promise resolving to a booleanto it to tell Sblendid which peripheral you want to connect to.
Sblendid.connect will use your criteria to scan your surroundings
and connect to and return the peripheral once it's found.
import Sblendid from "@sblendid/sblendid";
(async () => {
const peripheral = await Sblendid.connect("My Peripheral");
const peripheral = await Sblendid.connect("3A62F159");
const peripheral = await Sblendid.connect("00-14-22-01-23-45");
const peripheral = await Sblendid.connect(peripheral =>
peripheral.name.startsWith("My")
);
const peripheral = await Sblendid.connect(
async peripheral => await checkSomething(peripheral)
);
await Sblendid.powerOff();
})();
The return type of connect will be an instance of Peripheral. See
import Sblendid from "@sblendid/sblendid";
(async () => {
const peripheral = await Sblendid.connect("My Peripheral");
const services = await peripheral.getServices();
await Sblendid.powerOff();
})();
The return type of getServices will be an array of instances of Peripheral. See
import Sblendid from "@sblendid/sblendid";
(async () => {
const peripheral = await Sblendid.connect("My Peripheral");
const service = await peripheral.getService("a000");
const characteristics = await service.getCharacteristics();
await Sblendid.powerOff();
})();
Read Values
Unless you use
converters, values read will be Buffers
import Sblendid from "@sblendid/sblendid";
const batteryServiceUuid = "180f";
const batteryLevelUuid = "2a19";
(async () => {
const peripheral = await Sblendid.connect(peripheral =>
peripheral.hasService(batteryServiceUuid)
);
const batteryService = await peripheral.getService(batteryServiceUuid);
const batteryLevel = await batteryService.read(batteryLevelUuid);
console.log("Battery Level", batteryLevel.readUInt8(0), "%");
await Sblendid.powerOff();
})();
Subscribe Values
Unless you use
converters, values you get from a subscription will be Buffers
import Sblendid from "@sblendid/sblendid";
const batteryServiceUuid = "180f";
const batteryLevelUuid = "2a19";
(async () => {
const peripheral = await Sblendid.connect(peripheral =>
peripheral.hasService(batteryServiceUuid)
);
const batteryService = await peripheral.getService(batteryServiceUuid);
await batteryService.on(batteryLevelUuid, batteryLevel => {
console.log("Battery Level", batteryLevel.readUInt8(0), "%");
});
await Sblendid.powerOff();
})();
Write Values
Unless you use
converters, values you pass to a write operation must be Buffers
import Sblendid from "@sblendid/sblendid";
const alertServiceUuid = "1811";
const newAlertUuid = "2a44";
(async () => {
const peripheral = await Sblendid.connect(peripheral =>
peripheral.hasService(alertServiceUuid)
);
const alertService = await peripheral.getService(alertServiceUuid);
await alertService.write(newAlertUuid, Buffer.from("Message", "utf8");
await Sblendid.powerOff();
})();
You can find more examples in the Examples folder:
Running Examples
You can run any of these examples by cloning this repository, building the library and calling
yarn example:git clone git@github.com:LukasBombach/sblendid.git cd sblendid yarn && yarn build cd packages/sblendid yarn example examples/<filename>
Sblendid has 4 main classes
| Class | Desciption |
|---|---|
Sblendid | Lets you find and connect to peripherals |
Peripheral | Lets you connect to peripherals and read their services and RSSIs |
Service | Lets you read, write and subscribe to updates on values (characteristics) of a service as well as |
Characteristic | A representation of a single characteristic of a service that lets you read, write and subscribe to updates of a specific value. Usually you will not need to use this class as everything you can do with this on a single characteristic, you can already do with the service class on all available characteristics |
SblendidHere you can see the entire public API of the Sblendid class for an overview. You can find
a more detailed description below.
class Sblendid {
public adapter: Adapter;
constructor() {}
public static async powerOn(): Promise<Sblendid> {}
public static async powerOff(): Promise<Sblendid> {}
public static async connect(condition: Condition): Promise<Peripheral> {}
public async powerOn(): Promise<void> {}
public async powerOff(): Promise<void> {}
public async find(condition: Condition): Promise<Peripheral> {}
public startScanning(listener?: PeripheralListener): void {}
public stopScanning(): void {}
}
adapter - An instance of the low-level Bluetooth adapter
that Sblendid uses, right now this will be an instance of
@sblendid/adapter-node. See packages/adapter-nodestatic async powerOn(): Promise<Sblendid>Before you can use BLE on your machine you need to turn on your BLE adapter. This static method will turn on the adapter and return an instance of sblendid that you can then use to find and connect to peripherals
import Sblendid from "@sblendid/sblendid";
const sblendid = await Sblendid.powerOn();
sblendid.startScanning();
static async powerOff(): Promise<void>When you use BLE you need power on your BLE adapter (Your actual hardware). This library will keep the BLE adapter running while your node process runs. When you are done with using BLE you need to power off the BLE adapter again.
If you don't do this, your Node process will keep running after your script is done. I.e. you will see the last line of your code being executed, but your Node script just won't return to your console.
Don't worry, if you forgot to call powerOff, you can just press ctrl + c to stop your script and there will be no hard done whatsoever, It can just be very annoying.
import Sblendid from "@sblendid/sblendid";
const sblendid = await Sblendid.powerOn();
sblendid.startScanning();
await Sblendid.powerOff();
static async connect(condition: Condition): Promise<Peripheral>Often times you have a specific peripheral in mind you want to connect to. You would usually
There is a shortcut for that. You can call Sblendid.connect to do all that.
Pass either a peripheral name, uuid, address or callback function as an argument
and you will get a connected peripheral as return value once the peripheral has
been found.
The callback function will receive an instance of a Peripheral that represents any
peripheral found while scanning. The callback function can be sync or async
(i.e. return a Promise) and must always return aór resolve to a Boolean signaling
of the given peripheral is the one you were looking for. If true, Sblendid.connect
will stop scanning, connect to that peripheral and return it.
import Sblendid from "@sblendid/sblendid";
// By Name
const peripheral = await Sblendid.connect("My Peripheral");
// By UUID
const peripheral = await Sblendid.connect("3A62F159");
// By Address
const peripheral = await Sblendid.connect("00-14-22-01-23-45");
// With a callback
const peripheral = await Sblendid.connect(periperal =>
Boolean(periperal.connectable)
);
// With an async callback
const peripheral = await Sblendid.connect(
async periperal => await isPeripheralIAmLookingFor(periperal)
);
new Sblendid() (Constructor)You can instantiate Sblendid like any other class. It has no parameters. You will have to turn it on before using it though.
import Sblendid from "@sblendid/sblendid";
const sblendid = new Sblendid();
async powerOn(): Promise<void>If you instantiate Sblendid in your own, this method lets you turn on your BLE adapter. It returns a promise that resolves (with no value) when the adater ist powered on.
Note that you can also use const sblendid = await Sblendid.powerOn(); to achieve the
same thing.
import Sblendid from "@sblendid/sblendid";
const sblendid = new Sblendid();
await sblendid.powerOn();
async powerOff(): Promise<void>The powerOff method is available as a class method as well as an instance method.
They do exactly the same thing. It is only there for convencience in sutations where
you have an instance but not the class. Please refer to the documentation of
Sblendid.powerOff to read about it.
import Sblendid from "@sblendid/sblendid";
const sblendid = await Sblendid.powerOn();
sblendid.startScanning();
await sblendid.powerOff();
async find(condition: Condition): Promise<Peripheral>Will scan for a peripheral and return it once it's found. Unlike Sblendid.connect
find will not automatically connect to the peripheral. find will accept the same
parameters as Sblendid.connect to find a a peripheral.
Note that this is an instance method, so you will have to instantiate and turn on Sblendid first.
import Sblendid from "@sblendid/sblendid";
const sblendid = await Sblendid.powerOn();
const peripheral = await sblendid.find("My Peripheral");
startScanning(listener?: PeripheralListener): voidWill start scanning for peripherals. Instead of finding a specific peripheral
and returning it, this method will just scan your surroundings and call a
callback for every peripheral it finds. It will do so indefinitely until you
call sblendid.stopScanning(). This method has no return value and is not
asynchronous.
The callback function will receive a single argument which is an instance of
Peripheral.
Note that when you call
sblendid.startScanningmultiple times with different listeners only the last listener will be used and all others will be discarded.
import Sblendid from "@sblendid/sblendid";
function listener(peripheral) {
console.log("Found peripheral with uuid", peripheral.uuid);
}
const sblendid = await Sblendid.powerOn();
sblendid.startScanning(listener);
stopScanning(): voidWill tell sblendid to stop scanning. The listener you may have provided in
sblendid.startScanning will be discarded and not be called anymore.
import Sblendid from "@sblendid/sblendid";
function listener(peripheral) {
console.log("Found peripheral with uuid", peripheral.uuid);
}
const sblendid = await Sblendid.powerOn();
sblendid.startScanning(listener);
await new Promise(resolve => setTimeout(resolve, 1000));
sblendid.stopScanning();
PeripheralHere you can see the entire public API of the Peripheral class for an overview. You can find
a more detailed description below.
class Peripheral {
public uuid: PUUID;
public adapter: Adapter;
public name: string;
public address: string;
public addressType: AddressType;
public advertisement: Advertisement;
public connectable?: boolean;
public state: State;
constructor(uuid: PUUID, adapter: Adapter, options: Options) {}
public async connect(): Promise<void> {}
public async disconnect(): Promise<void> {}
public async getService(uuid: SUUID, converters?: Converters): Promise<Service<Converters> | undefined> {}
public async getServices(serviceConverters?: ServiceConverters): Promise<Service<any>[]> {}
public async hasService(uuid: SUUID): Promise<boolean> {}
public async getRssi(): Promise<number> {}
public isConnected(): boolean {}
}
uuid - The UUID of the peripheraladapter - An instance of the low-level Bluetooth adapter
that Sblendid uses, right now this will be an instance of
@sblendid/adapter-node. See packages/adapter-nodename - The localName of the peripheral. This
is the same as peripheral.advertisement.localName and will
be an empty string if localName on the advertisement is
not availableaddress - The address of the peripheraladdressType - The address type of the peripheral, can
either be public, random or unknownadvertisement - An object with the advertisement information of a peripheral. See packages/adapter-node/src/peripheral.tsconnectable - Whether or not the peripheral can be connected to. Important This is
an info the peripheral advertises itself with. Sometimes, even thought it says it's not
connectable, it actually is.state - The connection state of the peripheral, can either be connecting, connected, disconnecting or disconnectednew Peripheral(uuid: PUUID, adapter: Adapter, options: Options) (Constructor)Creates a new Peripheral instance
import { Peripheral } from "@sblendid/sblendid";
import Adapter from "@sblendid/adapter-node";
const options = {
address: "00-14-22-01-23-45",
addressType: "public",
advertisement: {
localName: "My Peripheral",
txPowerLevel: 10,
serviceUUIDs: ["f055e3", "143cba", "e72a1e"],
manufacturerData: Buffer.from([]),
serviceData: [
{
uuid: "43f9d8",
data: Buffer.from([])
}
]
},
connectable: true
};
const adapter = new Adapter();
const peripheral = new Peripheral("3A62F159", adapter, options);
However, you would usually create a Peripheral instance by
getting it from the Sblendid class using connect, find
or startScanning
import Sblendid from "@sblendid/sblendid";
const peripheral = Sblendid.connect();
const peripheral = new Sblendid().find();
new Sblendid().startScanning(peripheral => {});
To bring this API documentation close to how most people would use this library I will receive my
Periperalinstance from theSblendidclass instead of the constructor in the following examples
ServiceHere you can see the entire public API of the Service class for an overview. You can find
a more detailed description below.
class Service {
public uuid: SUUID;
public peripheral: Peripheral;
public async read(name: Name): Promise<Value> {}
public async write( name: Name, value: Value, withoutResponse?: boolean): Promise<void> {}
public async on(name: Name, listener: Listener): Promise<void> {}
public async off(name: Name, listener: Listener): Promise<void> {}
public async getCharacteristic(name: Name): Promise<Characteristic> {}
public async getCharacteristics(): Promise<Characteristic[]> {}
}
CharacteristicHere you can see the entire public API of the Characteristic class for an overview. You can find
a more detailed description below.
class Characteristic {
public uuid: CUUID;
public service: Service;
public properties: Properties;
public async read(): Promise<Value> {}
public async write(value: Value, withoutResponse?: boolean): Promise<void> {}
public async on(event: "notify", listener: Listener): Promise<void> {}
public async off(event: "notify", listener: Listener): Promise<void> {}
}
MIT
FAQs
Bluetooth Low Energy for JavaScript
The npm package @sblendid/sblendid receives a total of 0 weekly downloads. As such, @sblendid/sblendid popularity was classified as not popular.
We found that @sblendid/sblendid demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
OWASP’s 2025 Top 10 introduces Software Supply Chain Failures as a new category, reflecting rising concern over dependency and build system risks.

Research
/Security News
Socket researchers discovered nine malicious NuGet packages that use time-delayed payloads to crash applications and corrupt industrial control systems.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.