The Easy BLE
library is an advanced BLE management tool for ZeppOS 3.0
watches that features an automated profile generator, a hybrid asynchronous and sequential queue for efficient handling of all operations including writing and reading, user-friendly string-based interactions, seamless auto-conversions of data and addresses, support for multiple data types, and simplified device management through MAC address-centric commands, all designed to enhance usability and streamline BLE communications.
npm i @silver-zepp/easy-ble
// install -> npm i @silver-zepp/easy-ble
import BLEMaster from "@silver-zepp/easy-ble"
const ble = new BLEMaster();
// the mac of a device you are connecting to
const MAC = "1A:2B:3C:4D:5E:6F";
// simplified object that describes a profile
const services = {
// service #1
"FF00": { // service UUID
"FF02": [], // READ chara UUID
"FF03": ["2902"], // NOTIFY chara UUID
// ^--- descriptor UUID
},
// ... add other services here if needed
}
// connect to a device
ble.connect(MAC, (connect_result)=>{
// proceed further if [bool] connected is true
if (connect_result.connected){
// generate a complex profile object providing description of its services
const profile_object = ble.generateProfileObject(services);
// start listening for the response from watch's backend
ble.startListener(profile_object, (response)=> {
if (response.success){
// first subcribe to the events
ble.on.charaValueArrived((uuid, data, len)=> {
console.log("Read result:", uuid, data, len);
}
);
// then manipulate - read/write/etc
ble.read.characteristic("FF02");
// As a result you should log
// Read result: 'FF02' 'BAT_LVL_77' '10'
}
});
}
});
Starts scanning for BLE devices.
{Function} response_callback
- Callback function called with each device's scan result.{Object} [options={}]
- Optional parameters for the scan.{number} [options.duration]
- Duration of the scan in milliseconds. Auto-stops after this duration.{Function} [options.on_duration]
- Callback function called when the scan stops after the specified duration.{number} [options.throttle_interval=1000]
- Interval in milliseconds to throttle the processing of scan results.{boolean} [options.allow_duplicates=false]
- Whether to include duplicate devices in each callback. Defaults to false.
// example: start scanning for devices and log each found device
.startScan((device) => { console.log('Found device:', device); });
// advanced example: start scanning for 10 seconds with a custom throttle interval and allow duplicates, then stop and log
.startScan((device) => { console.log('Found device during scan:', device); },
{ duration: 10000, throttle_interval: 500, allow_duplicates: true, on_duration: () => console.log('Scan complete') });
{boolean} true if the scan started successfully, false otherwise.
Stops the ongoing scanning process for BLE devices.
// Simply stop the scan
.stopScan();
// Advanced example: start scanning for devices and then stop scanning after the device was found
.startScan((device) => {
if (.get.hasMAC("1A:2B:3C:4D:5E:6F"))
.stopScan();
});
{boolean} - true if the scan was successfully stopped, false if there was an error in stopping the scan.
Attempts to connect to a BLE device.
dev_addr
{string} - The MAC address of the device to connect to.response_callback
{function} - Callback function that receives the result of the connection attempt. The callback is called with an object containing two properties:connected
: A boolean indicating if the connection was successful.status
: A string indicating the connection status. Possible values areconnected
,invalid mac
,in progress
,failed
, ordisconnected
.
// Connect to a device and log the result
.connect("1A:2B:3C:4D:5E:6F", (result) => {
if (result.connected) {
console.log('Connected to device');
} else {
console.log('Failed to connect. Status:', result.status);
}
});
{boolean} - true if the connection attempt started successfully, false otherwise.
Disconnects from a BLE device.
// Disconnect from a device
.disconnect();
{boolean} - true if the disconnection was successful, false if it failed or if the device was not connected.
Attempts to pair with a BLE device. WARNING: This method might not work as expected and could potentially cause crashes. Use with caution.
// Attempt to pair with a device
const success = .pair();
if (success) console.log('Pairing initiated successfully');
else console.log('Pairing failed or device not connected');
{boolean} - Returns true if the call to initiate pairing with the device succeeded, false if it failed or if the device was not connected.
Starts listening for profile preparation events and builds a profile for interacting with a BLE device.
profile_object
{Object} - The profile object describing how to interact with the BLE device. This should be generated usinggenerateProfileObject
method.response_callback
{Function} - Callback function called with the result of the profile preparation. The callback receives an object containing 'success', 'message', and optionally 'code' properties.
// Start listener with a profile object
const profile_object = .generateProfileObject(services); // detailed profile object
.startListener(profile_object, (response) => {
if (response.success) {
console.log('Profile preparation successful:', response.message);
} else {
console.log('Profile preparation failed:', response.message, 'Code:', response.code);
}
});
{void} - This method doesn’t return a value but invokes the response callback with the result of the profile preparation.
Generates a generic profile object for interacting with a BLE device.
services
{object} - A list of services with their characteristics and descriptors. Each service is identified by its UUID and contains a map of its characteristics. Each characteristic, identified by its UUID, is an array of its descriptor UUIDs.permissions
{object} [permissions={}] - Optional. An object specifying custom permissions for characteristics and descriptors. If not provided, defaults to a permission value of 32 (all permissions) for each entry.
// Example of generating a profile object for a device with custom permissions
const services = {
'service_uuid': {
'char_uuid_1': ['desc_uuid_1', 'desc_uuid_2'],
'char_uuid_2': []
}
// other services...
};
const permissions = {
'char_uuid_1': PERMISSIONS.READ, // no need to provide perms for all UUIDs
};
const profile = .generateProfileObject(services, permissions);
{object|null} - A generic profile object for the device, or null if the device was not found. The profile object includes device connection information, services, characteristics, and their permissions.
Quits all interactions with the currently connected device and cleans up.
// Quit interaction with a connected device
.quit();
Sets the debug log level for the BLEMaster class.
debug_level
{number} - The debug level to set. Possible values:0
- No logs1
- Critical errors only2
- Errors and warnings3
- All logs (including debug information)
// Show all logs
BLEMaster.SetDebugLevel(3);
Writes data to a characteristic of a BLE device. This operation is queued to ensure proper synchronization with other BLE operations.
uuid
{string} - The UUID of the characteristic to write to.data
{string|ArrayBuffer|Uint8Array} - The data to write, in various formats.write_without_response
{boolean} [write_without_response=false] - If true, writes without using the queue and without waiting for a response.
// Write a string to a characteristic
.write.characteristic('char_uuid', 'Hello World');
// Fast write an ArrayBuffer to a characteristic and don't wait for response
const buffer = new Uint8Array([1, 2, 3]).buffer;
.write.characteristic('char_uuid', buffer, true);
Writes data to a descriptor of a device's characteristic. This operation is queued to ensure proper synchronization with other BLE operations.
chara
{string} - The UUID of the characteristic that the descriptor belongs to.desc
{string} - The UUID of the descriptor to write to.data
{string|ArrayBuffer|Uint8Array} - The data to write. Can be an ArrayBuffer, a Uint8Array, a hex string, or a regular string.
// Write a hex string to a descriptor
.write.descriptor('char_uuid', 'desc_uuid', '0100');
// Write an ArrayBuffer to a descriptor
const buffer = new Uint8Array([1, 2, 3]).buffer;
.write.descriptor('char_uuid', 'desc_uuid', buffer);
Enables or disables notifications for a characteristic by writing to the CCCD (Client Characteristic Configuration Descriptor). This operation is queued to ensure proper synchronization with other BLE operations.
chara
{string} - The UUID of the characteristic.enable
{boolean} - Set to true to enable notifications, false to disable.
// Toggle notifications for a characteristic (true/false)
.write.enableCharaNotifications('char_uuid', true);
Reads data from a characteristic of a BLE device. This operation is queued to ensure proper synchronization with other BLE operations.
uuid
{string} - The UUID of the characteristic to read from.
// Read data from a characteristic
const read = .read.characteristic('char_uuid');
if (read.success) console.log('Read successful');
else console.log('Read failed:', read.error);
{Object} - An object containing a ‘success’ property and optionally an ‘error’ property.
Reads data from a descriptor of a characteristic of a BLE device. This operation is queued to ensure proper synchronization with other BLE operations.
chara
{string} - The UUID of the characteristic.desc
{string} - The UUID of the descriptor to read from.
// Read data from a descriptor
const desc = .read.descriptor("1A:2B:3C:4D:5E:6F", 'char_uuid', 'desc_uuid');
if (desc.success) console.log('Descriptor read successful');
else console.log('Descriptor read failed:', desc.error);
{Object} - An object containing a ‘success’ property and optionally an ‘error’ property.
Registers a callback for the characteristic read complete event. This callback is triggered after a read operation on a characteristic is completed.
callback
{Function} - The callback to execute on event trigger.
// Register callback for characteristic read complete event
.on.charaReadComplete((uuid, status) => {
console.log('Characteristic read complete for UUID:', uuid, 'with status:', status);
});
uuid {string} - The UUID of the characteristic. status {number} - The status of the read operation.
Registers a callback for the characteristic value arrived event. This callback is triggered when new data is received from a characteristic.
callback
{Function} - The callback to execute on event trigger.
// Register callback for characteristic value arrived event
.on.charaValueArrived((uuid, data, length) => {
console.log('Value arrived for UUID:', uuid, 'Data:', data, 'Length:', length);
});
uuid {string} - The UUID of the characteristic. data {ArrayBuffer} - The data received from the characteristic. length {number} - The length of the data.
Registers a callback for the characteristic write complete event. This callback is triggered after a write operation on a characteristic is completed.
callback
{Function} - The callback to execute on event trigger.
// Register callback for characteristic write complete event
.on.charaWriteComplete((uuid, status) => {
console.log('Characteristic write complete for UUID:', uuid, 'Status:', status);
});
uuid {string} - The UUID of the characteristic. status {number} - The status of the write operation.
Registers a callback for the descriptor read complete event. This callback is triggered after a read operation on a descriptor is completed.
callback
{Function} - The callback to execute on event trigger.
// Register callback for descriptor read complete event
.on.descReadComplete((chara, desc, status) => {
console.log(`Descriptor read complete for Characteristic UUID: ${chara},
Descriptor UUID: ${desc}, Status: ${status}`);
});
chara {string} - UUID of the characteristic desc {string} - UUID of the descriptor status {number} - Status of the read operation
Registers a callback for the descriptor value arrived event. This callback is triggered when new data arrives at a descriptor.
callback
{Function} - The callback to execute on event trigger.
// Register callback for descriptor value arrived event
.on.descValueArrived((chara, desc, data, length) => {
console.log(`Descriptor value arrived for Characteristic UUID: ${chara},
Descriptor UUID: ${desc}, Data: ${data}, Length: ${length}`);
});
chara {string} - UUID of the characteristic desc {string} - UUID of the descriptor data {ArrayBuffer} - Data received length {number} - Length of the data
Registers a callback for the descriptor write complete event. This callback is triggered after a write operation on a descriptor is completed.
callback
{Function} - The callback to execute on event trigger.
// Register callback for descriptor write complete event
.on.descWriteComplete((chara, desc, status) => {
console.log(`Descriptor write complete for Characteristic UUID: ${chara},
Descriptor UUID: ${desc}, Status: ${status}`);
});
chara {string} - UUID of the characteristic desc {string} - UUID of the descriptor status {number} - Status of the write operation
Registers a callback for the characteristic notification event. This callback is triggered when a notification is received from a characteristic.
callback
{Function} - The callback to execute on event trigger.
// Register callback for characteristic notification event
.on.charaNotification((uuid, data, length) => {
console.log(`Notification received for UUID: ${uuid}, Data: ${data}, Length: ${length}`);
});
uuid {string} - UUID of the characteristic data {ArrayBuffer} - Notification data length {number} - Length of the data
Registers a callback for the service change begin event. This callback is triggered when a BLE service change process begins.
callback
{Function} - The callback to execute on event trigger.
// Register callback for service change begin event
.on.serviceChangeBegin(() => {
console.log(`Service change has begun`);
});
Registers a callback for the service change end event. This callback is triggered when a BLE service change process ends.
callback
{Function} - The callback to execute on event trigger.
// Register callback for service change end event
.on.serviceChangeEnd(() => {
console.log(`Service change has ended`);
});
Deregisters the callback for characteristic read complete event.
.off.charaReadComplete();
Deregisters the callback for characteristic value arrived event.
.off.charaValueArrived();
Deregisters the callback for characteristic write complete event.
.off.charaWriteComplete();
Deregisters the callback for characteristic write complete event.
.off.charaWriteComplete();
Deregisters the callback for descriptor value arrived event.
.off.descValueArrived();
Deregisters the callback for descriptor write complete event.
.off.descWriteComplete();
Deregisters the callback for characteristic notification event.
.off.charaNotification();
Deregisters the callback for service change begin event.
.off.serviceChangeBegin();
Deregisters the callback for service change end event.
.off.serviceChangeEnd();
Deregisters all callbacks associated with the current BLE connection. This method ensures no event callbacks remain active after stopping BLE operations.
.off.deregisterAll();
Retrieves information about all discovered devices.
// Get all discovered devices
const devices = .get.devices();
console.log('Discovered devices:', JSON.stringify(devices));
{Object} An object containing information about all discovered devices.
Checks if a specific device is currently connected.
// Check if a device is connected
const is_connected = .get.isConnected();
console.log('Is device connected:', is_connected);
{boolean} True if the device is connected, false otherwise.
Checks if a device with a specific MAC address has been discovered.
dev_addr
{string} - The MAC address of the device.
// Check if a specific mac has been discovered
const has_mac = .get.hasMAC("1A:2B:3C:4D:5E:6F");
console.log('Has the mac been discovered:', has_mac);
{boolean} true if the device has been discovered, false otherwise.
Checks if any discovered device has a specific device name.
{string} dev_name
- The device name to check for.
// example: check if any device has the name "my ble peripheral"
const has_dev_name = .get.hasDeviceName("my ble peripheral");
console.log('Has device name "my ble peripheral":', has_dev_name);
{boolean} true if any device has the specified device name, false otherwise.
Checks if any discovered device has a specific service UUID.
{string} service_uuid
- The UUID of the service to check for.
// Check if any device has a specific service
const has_service = .get.hasService("1812");
console.log('Has service 1812:', has_service);
{boolean} true if any device has the specified service, false otherwise.
Checks if any discovered device contains specific service data.
{string} service_data
- The service data to check for.
// Check if any device contains specific service data
const has_service_data = .get.hasServiceData("somedata");
console.log('Has service data "somedata":', has_service_data);
{boolean} true if any device contains the specified service data, false otherwise.
Checks if any discovered device has a specific vendor data.
{string} vendor_data
- The vendor data to check for.
// Check if any device has "zepp" data
const has_vendor_data = .get.hasVendorData("zepp");
console.log('Has vendor "zepp":', has_vendor_data);
{boolean} true if any device has the specified vendor data, false otherwise.
Checks if any discovered device has a specific vendor ID.
{number} vendor_id
- The vendor ID to check for.
// example: Check if any device has vendor ID 777
const has_vendor_id = .get.hasVendorID(777);
console.log('Has vendor ID 777:', has_vendor_id);
{boolean} true if any device has the specified vendor ID, false otherwise.
Retrieves the profile pointer ID of a specific device. This is only useful if you need to communicate directly with hmBle.mst
methods.
// Get the profile ID of a device
const profile_pid = .get.profilePID();
console.log('Profile pointer ID:', profile_pid);
{number|null} The profile pointer ID of the device if available, null otherwise.
Retrieves the connection ID of a specific device. This is only useful if you need to communicate directly with hmBle.mst
methods.
// Get the connection ID of a device
const connection_id = .get.connectionID();
console.log('Connection ID:', connection_id);
{number|null} The connection ID of the device if available, null otherwise.
Converts an ArrayBuffer to a string of hexadecimal numbers. This function is useful when you need to represent binary data in a readable hexadecimal string format. For example, it can be used to display BLE device addresses or data in a human-readable form.
buffer
{ArrayBuffer} - The ArrayBuffer to be converted.
// Convert an ArrayBuffer to a hexadecimal string
const buffer = new Uint8Array([10, 20, 30]).buffer;
const hex_str = ab2hex(buffer);
console.log(hex_str); // Output: '0A 14 1E'
{string} The hexadecimal string representation of the ArrayBuffer. Each byte is represented as a two-character hex code.
Converts an ArrayBuffer into a string. This function is used when you need to convert binary data (ArrayBuffer) into a regular JavaScript string. It's particularly useful for converting data received from BLE devices into text, assuming the data represents text in a compatible encoding (e.g., UTF-8).
buffer
{ArrayBuffer} - The ArrayBuffer to be converted.
// Convert an ArrayBuffer to a string
const buffer = new Uint8Array([72, 101, 108, 108, 111]).buffer; // 'Hello' in ASCII
const str = ab2str(buffer);
console.log(str); // output: 'Hello'
{string} The resulting string. Note that the output is dependent on the encoding of the byte data in the ArrayBuffer.
Converts an ArrayBuffer to a number. This function is useful when you need to represent binary data in a readable number format. For example, it can be used to display BLE device battery levels or other data in a human-readable form.
{ArrayBuffer} buffer
- The ArrayBuffer to be converted.
// example: convert an ArrayBuffer to a number
const buffer = new Uint8Array([81]).buffer;
const num = ab2num(buffer);
console.log(num); // Output: 81
{number} The number representation of the ArrayBuffer.
Object containing BLE permissions. Each permission is a property with a detailed description and a numeric value. In many scenarios, it's sufficient to use the built-in generateProfileObject(...) auto-permission 32. However, for complex and encrypted communications, specific permissions defined here may be required.
READ
: Allows reading the characteristic value.READ_ENCRYPTED
: Allows reading the characteristic value with an encrypted link.READ_ENCRYPTED_MITM
: Allows reading the characteristic value with an encrypted and authenticated link (MITM protection).WRITE
: Allows writing the characteristic value.WRITE_ENCRYPTED
: Allows writing the characteristic value with an encrypted link.WRITE_ENCRYPTED_MITM
: Allows writing the characteristic value with an encrypted and authenticated link (MITM protection).WRITE_SIGNED
: Allows writing the characteristic value with a signed write (without response).WRITE_SIGNED_MITM
: Allows writing the characteristic value with a signed write (without response) and authenticated link (MITM protection).READ_DESCRIPTOR
: Allows reading the descriptor value.WRITE_DESCRIPTOR
: Allows writing the descriptor value.READ_WRITE_DESCRIPTOR
: Allows both reading and writing the descriptor value.NONE
: No permissions granted.ALL
: All permissions granted.
Each property is an object with a description
and a value
. The description
is a string that explains the permission, and the value
is a numeric value representing the permission.