bare-bluetooth-android
Advanced tools
Sorry, the diff of this file is too big to display
| module.exports = require.addon() |
| cmake_minimum_required(VERSION 4.0) | ||
| find_package(cmake-bare REQUIRED PATHS node_modules/cmake-bare) | ||
| find_package(cmake-fetch REQUIRED PATHS node_modules/cmake-fetch) | ||
| find_package(cmake-android REQUIRED PATHS node_modules/cmake-android) | ||
| project(bare_bluetooth_android C CXX) | ||
| use_java() | ||
| fetch_package("github:holepunchto/libjstl") | ||
| fetch_package("github:holepunchto/libjnitl") | ||
| add_bare_module(bare_bluetooth_android) | ||
| target_sources( | ||
| ${bare_bluetooth_android} | ||
| PRIVATE | ||
| binding.cc | ||
| ) | ||
| target_link_libraries( | ||
| ${bare_bluetooth_android} | ||
| PUBLIC | ||
| jstl | ||
| jnitl | ||
| ) | ||
| set_target_properties( | ||
| ${bare_bluetooth_android} | ||
| PROPERTIES | ||
| C_STANDARD 11 | ||
| CXX_STANDARD 20 | ||
| CXX_SCAN_FOR_MODULES OFF | ||
| POSITION_INDEPENDENT_CODE ON | ||
| ) | ||
| find_android_jar(android_jar) | ||
| set(CMAKE_JAVA_COMPILE_FLAGS --release 17) | ||
| add_dex( | ||
| bare_bluetooth_classes | ||
| SOURCES | ||
| lib/ScanCallback.java | ||
| lib/GattCallback.java | ||
| lib/GattServerCallback.java | ||
| lib/AdvertiseCallback.java | ||
| INCLUDE_JARS | ||
| ${android_jar} | ||
| ) | ||
| bare_target(target) | ||
| bare_module_target("." _module NAME _name) | ||
| install( | ||
| FILES | ||
| $<TARGET_PROPERTY:bare_bluetooth_classes,DEX_FILE> | ||
| DESTINATION ${target}/${_name} | ||
| ) |
+13
| export { default as L2CAPChannel } from './lib/channel' | ||
| export { default as Service, ServiceOptions } from './lib/service' | ||
| export { default as Characteristic, CharacteristicOptions } from './lib/characteristic' | ||
| export { | ||
| default as Server, | ||
| BluetoothState, | ||
| AdvertisingOptions, | ||
| ChannelOptions, | ||
| ReadRequest, | ||
| WriteRequest | ||
| } from './lib/server' | ||
| export { default as Central } from './lib/central' | ||
| export { default as Peripheral, PeripheralOptions } from './lib/peripheral' |
+6
| exports.Central = require('./lib/central') | ||
| exports.Peripheral = require('./lib/peripheral') | ||
| exports.Server = require('./lib/server') | ||
| exports.L2CAPChannel = require('./lib/channel') | ||
| exports.Service = require('./lib/service') | ||
| exports.Characteristic = require('./lib/characteristic') |
| package to.holepunch.bare.bluetooth; | ||
| import android.bluetooth.le.AdvertiseSettings; | ||
| public final class AdvertiseCallback extends android.bluetooth.le.AdvertiseCallback { | ||
| private final long nativePointer; | ||
| public AdvertiseCallback(long nativePointer) { | ||
| this.nativePointer = nativePointer; | ||
| } | ||
| @Override | ||
| public void | ||
| onStartSuccess(AdvertiseSettings settingsInEffect) { | ||
| nativeOnStartSuccess(nativePointer, settingsInEffect); | ||
| } | ||
| @Override | ||
| public void | ||
| onStartFailure(int errorCode) { | ||
| nativeOnStartFailure(nativePointer, errorCode); | ||
| } | ||
| private static native void | ||
| nativeOnStartSuccess(long nativePointer, AdvertiseSettings settingsInEffect); | ||
| private static native void | ||
| nativeOnStartFailure(long nativePointer, int errorCode); | ||
| } |
| import { EventEmitter, EventMap } from 'bare-events' | ||
| import Peripheral from './peripheral' | ||
| export type BluetoothState = 'off' | 'turningOn' | 'on' | 'turningOff' | ||
| export interface CentralEventMap extends EventMap { | ||
| stateChange: [state: BluetoothState] | ||
| discover: [peripheral: Peripheral] | ||
| connect: [peripheral: Peripheral, error?: string] | ||
| disconnect: [peripheral: Peripheral | null, error?: string] | ||
| connectFail: [id: string, error: string] | ||
| scanFail: [errorCode: number] | ||
| } | ||
| export default class Central extends EventEmitter<CentralEventMap> { | ||
| constructor() | ||
| readonly state: BluetoothState | ||
| startScan(serviceUUIDs?: string[]): void | ||
| stopScan(): void | ||
| connect(peripheral: Peripheral): void | ||
| disconnect(peripheral: Peripheral): void | ||
| destroy(): void | ||
| static readonly STATE_OFF: number | ||
| static readonly STATE_TURNING_ON: number | ||
| static readonly STATE_ON: number | ||
| static readonly STATE_TURNING_OFF: number | ||
| } |
+131
| const EventEmitter = require('bare-events') | ||
| const binding = require('../binding') | ||
| const Peripheral = require('./peripheral') | ||
| const STATES = { | ||
| [binding.STATE_OFF]: 'off', | ||
| [binding.STATE_TURNING_ON]: 'turningOn', | ||
| [binding.STATE_ON]: 'on', | ||
| [binding.STATE_TURNING_OFF]: 'turningOff' | ||
| } | ||
| module.exports = exports = class Central extends EventEmitter { | ||
| constructor() { | ||
| super() | ||
| this._handle = binding.centralInit( | ||
| this, | ||
| this._onstatechange, | ||
| this._ondiscover, | ||
| this._onconnect, | ||
| this._ondisconnect, | ||
| this._onconnectfail, | ||
| this._onscanfail | ||
| ) | ||
| this._peripherals = new Map() | ||
| this._connected = new Map() | ||
| this._state = 'off' | ||
| } | ||
| get state() { | ||
| return this._state | ||
| } | ||
| startScan(serviceUUIDs, opts = {}) { | ||
| const uuids = serviceUUIDs ? serviceUUIDs.map((s) => binding.createUUID(s)) : null | ||
| const scanMode = opts.scanMode === undefined ? null : opts.scanMode | ||
| binding.centralStartScan(this._handle, uuids, scanMode) | ||
| } | ||
| stopScan() { | ||
| binding.centralStopScan(this._handle) | ||
| this._peripherals.clear() | ||
| } | ||
| connect(peripheral) { | ||
| binding.centralConnect(this._handle, peripheral.handle) | ||
| } | ||
| disconnect(peripheral) { | ||
| binding.centralDisconnect(this._handle, peripheral._connectHandle) | ||
| } | ||
| destroy() { | ||
| for (const peripheral of this._connected.values()) { | ||
| peripheral.destroy() | ||
| } | ||
| this._connected.clear() | ||
| binding.centralDestroy(this._handle) | ||
| } | ||
| [Symbol.for('bare.inspect')]() { | ||
| return { | ||
| __proto__: { constructor: Central }, | ||
| state: this._state | ||
| } | ||
| } | ||
| _onstatechange(state) { | ||
| this._state = STATES[state] || 'off' | ||
| this.emit('stateChange', this._state) | ||
| } | ||
| _ondiscover(handle, id, name, rssi) { | ||
| let peripheral = this._peripherals.get(id) | ||
| if (peripheral) { | ||
| peripheral.handle = handle | ||
| peripheral.rssi = rssi | ||
| if (name) peripheral.name = name | ||
| } else { | ||
| peripheral = { handle, id, name, rssi } | ||
| this._peripherals.set(id, peripheral) | ||
| } | ||
| this.emit('discover', peripheral) | ||
| } | ||
| _onconnect(handle, id) { | ||
| const discovered = this._peripherals.get(id) || null | ||
| const peripheral = new Peripheral(handle, { | ||
| id, | ||
| name: discovered ? discovered.name : null, | ||
| connectHandle: handle | ||
| }) | ||
| this._connected.set(id, peripheral) | ||
| this.emit('connect', peripheral) | ||
| } | ||
| _ondisconnect(id, error) { | ||
| const peripheral = this._connected.get(id) || null | ||
| if (peripheral) { | ||
| peripheral._ondisconnect(error || null) | ||
| peripheral.destroy() | ||
| } | ||
| this._connected.delete(id) | ||
| this.emit('disconnect', peripheral, error || null) | ||
| } | ||
| _onconnectfail(id, error) { | ||
| this.emit('connectFail', id, error) | ||
| } | ||
| _onscanfail(errorCode) { | ||
| this.emit('scanFail', errorCode) | ||
| } | ||
| } | ||
| exports.STATE_OFF = binding.STATE_OFF | ||
| exports.STATE_TURNING_ON = binding.STATE_TURNING_ON | ||
| exports.STATE_ON = binding.STATE_ON | ||
| exports.STATE_TURNING_OFF = binding.STATE_TURNING_OFF | ||
| exports.SCAN_MODE_OPPORTUNISTIC = binding.SCAN_MODE_OPPORTUNISTIC | ||
| exports.SCAN_MODE_LOW_POWER = binding.SCAN_MODE_LOW_POWER | ||
| exports.SCAN_MODE_BALANCED = binding.SCAN_MODE_BALANCED | ||
| exports.SCAN_MODE_LOW_LATENCY = binding.SCAN_MODE_LOW_LATENCY |
| import { Duplex } from 'bare-stream' | ||
| export default class L2CAPChannel extends Duplex { | ||
| constructor(channelHandle: ArrayBuffer) | ||
| readonly psm: number | ||
| readonly peer: string | null | ||
| } |
| const { Duplex } = require('bare-stream') | ||
| const binding = require('../binding') | ||
| module.exports = exports = class L2CAPChannel extends Duplex { | ||
| constructor(channelHandle) { | ||
| super({ | ||
| allowHalfOpen: false | ||
| }) | ||
| this._channelHandle = channelHandle | ||
| this._handle = binding.l2capInit( | ||
| channelHandle, | ||
| this, | ||
| this._ondata, | ||
| this._ondrain, | ||
| this._onend, | ||
| this._onerror, | ||
| this._onclose, | ||
| this._onopen | ||
| ) | ||
| } | ||
| get psm() { | ||
| return binding.l2capPsm(this._handle) | ||
| } | ||
| get peer() { | ||
| return binding.l2capPeer(this._handle) | ||
| } | ||
| _open(cb) { | ||
| binding.l2capOpen(this._handle) | ||
| cb() | ||
| } | ||
| _write(chunk, _encoding, cb) { | ||
| const bytesWritten = binding.l2capWrite(this._handle, chunk) | ||
| if (bytesWritten === 0) { | ||
| cb(new Error('Channel not ready or destroyed')) | ||
| } else { | ||
| cb(null) | ||
| } | ||
| } | ||
| _destroy(err, cb) { | ||
| binding.l2capEnd(this._handle) | ||
| cb(err) | ||
| } | ||
| [Symbol.for('bare.inspect')]() { | ||
| return { | ||
| __proto__: { constructor: L2CAPChannel }, | ||
| destroyed: this.destroyed | ||
| } | ||
| } | ||
| _ondata(data) { | ||
| this.push(data) | ||
| } | ||
| _ondrain() { | ||
| this.emit('drain') | ||
| } | ||
| _onend() { | ||
| this.push(null) | ||
| } | ||
| _onerror(message) { | ||
| this.emit('error', new Error(message)) | ||
| } | ||
| _onclose() { | ||
| this.emit('close') | ||
| } | ||
| _onopen() { | ||
| this.emit('open') | ||
| } | ||
| } |
| export default class Characteristic { | ||
| constructor(uuid: string, opts?: CharacteristicOptions) | ||
| readonly uuid: string | ||
| readonly properties: number | ||
| readonly permissions: number | null | ||
| value: Uint8Array | null | ||
| static readonly PROPERTY_READ: number | ||
| static readonly PROPERTY_WRITE_WITHOUT_RESPONSE: number | ||
| static readonly PROPERTY_WRITE: number | ||
| static readonly PROPERTY_NOTIFY: number | ||
| static readonly PROPERTY_INDICATE: number | ||
| } | ||
| export interface CharacteristicOptions { | ||
| read?: boolean | ||
| write?: boolean | ||
| writeWithoutResponse?: boolean | ||
| notify?: boolean | ||
| indicate?: boolean | ||
| permissions?: number | ||
| value?: Uint8Array | null | ||
| } |
| module.exports = exports = class Characteristic { | ||
| constructor(uuid, opts = {}) { | ||
| this._uuid = uuid | ||
| this._properties = 0 | ||
| this._permissions = opts.permissions === undefined ? null : opts.permissions | ||
| this._handle = null | ||
| this._value = opts.value || null | ||
| if (opts.read) this._properties |= Characteristic.PROPERTY_READ | ||
| if (opts.write) this._properties |= Characteristic.PROPERTY_WRITE | ||
| if (opts.writeWithoutResponse) { | ||
| this._properties |= Characteristic.PROPERTY_WRITE_WITHOUT_RESPONSE | ||
| } | ||
| if (opts.notify) this._properties |= Characteristic.PROPERTY_NOTIFY | ||
| if (opts.indicate) this._properties |= Characteristic.PROPERTY_INDICATE | ||
| } | ||
| get uuid() { | ||
| return this._uuid | ||
| } | ||
| get properties() { | ||
| return this._properties | ||
| } | ||
| get permissions() { | ||
| return this._permissions | ||
| } | ||
| get value() { | ||
| return this._value | ||
| } | ||
| set value(val) { | ||
| this._value = val | ||
| } | ||
| [Symbol.for('bare.inspect')]() { | ||
| return { | ||
| __proto__: { constructor: Characteristic }, | ||
| uuid: this._uuid | ||
| } | ||
| } | ||
| } | ||
| exports.PROPERTY_READ = 0x02 | ||
| exports.PROPERTY_WRITE_WITHOUT_RESPONSE = 0x04 | ||
| exports.PROPERTY_WRITE = 0x08 | ||
| exports.PROPERTY_NOTIFY = 0x10 | ||
| exports.PROPERTY_INDICATE = 0x20 |
| package to.holepunch.bare.bluetooth; | ||
| import android.bluetooth.BluetoothGatt; | ||
| import android.bluetooth.BluetoothGattCharacteristic; | ||
| import android.bluetooth.BluetoothGattDescriptor; | ||
| public final class GattCallback extends android.bluetooth.BluetoothGattCallback { | ||
| private final long nativePointer; | ||
| public GattCallback(long nativePointer) { | ||
| this.nativePointer = nativePointer; | ||
| } | ||
| @Override | ||
| public void | ||
| onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { | ||
| nativeOnConnectionStateChange(nativePointer, gatt, status, newState); | ||
| } | ||
| @Override | ||
| public void | ||
| onServicesDiscovered(BluetoothGatt gatt, int status) { | ||
| nativeOnServicesDiscovered(nativePointer, gatt, status); | ||
| } | ||
| @Override | ||
| public void | ||
| onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value, int status) { | ||
| nativeOnCharacteristicRead(nativePointer, gatt, characteristic, value, status); | ||
| } | ||
| @Override | ||
| public void | ||
| onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { | ||
| nativeOnCharacteristicWrite(nativePointer, gatt, characteristic, status); | ||
| } | ||
| @Override | ||
| public void | ||
| onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value) { | ||
| nativeOnCharacteristicChanged(nativePointer, gatt, characteristic, value); | ||
| } | ||
| @Override | ||
| public void | ||
| onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { | ||
| nativeOnDescriptorWrite(nativePointer, gatt, descriptor, status); | ||
| } | ||
| @Override | ||
| public void | ||
| onMtuChanged(BluetoothGatt gatt, int mtu, int status) { | ||
| nativeOnMtuChanged(nativePointer, gatt, mtu, status); | ||
| } | ||
| private static native void | ||
| nativeOnConnectionStateChange(long nativePointer, BluetoothGatt gatt, int status, int newState); | ||
| private static native void | ||
| nativeOnServicesDiscovered(long nativePointer, BluetoothGatt gatt, int status); | ||
| private static native void | ||
| nativeOnCharacteristicRead(long nativePointer, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value, int status); | ||
| private static native void | ||
| nativeOnCharacteristicWrite(long nativePointer, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status); | ||
| private static native void | ||
| nativeOnCharacteristicChanged(long nativePointer, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, byte[] value); | ||
| private static native void | ||
| nativeOnDescriptorWrite(long nativePointer, BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status); | ||
| private static native void | ||
| nativeOnMtuChanged(long nativePointer, BluetoothGatt gatt, int mtu, int status); | ||
| } |
| package to.holepunch.bare.bluetooth; | ||
| import android.bluetooth.BluetoothDevice; | ||
| import android.bluetooth.BluetoothGattCharacteristic; | ||
| import android.bluetooth.BluetoothGattDescriptor; | ||
| import android.bluetooth.BluetoothGattServer; | ||
| import android.bluetooth.BluetoothGattService; | ||
| public final class GattServerCallback extends android.bluetooth.BluetoothGattServerCallback { | ||
| private final long nativePointer; | ||
| public GattServerCallback(long nativePointer) { | ||
| this.nativePointer = nativePointer; | ||
| } | ||
| @Override | ||
| public void | ||
| onConnectionStateChange(BluetoothDevice device, int status, int newState) { | ||
| nativeOnConnectionStateChange(nativePointer, device, status, newState); | ||
| } | ||
| @Override | ||
| public void | ||
| onServiceAdded(int status, BluetoothGattService service) { | ||
| nativeOnServiceAdded(nativePointer, status, service); | ||
| } | ||
| @Override | ||
| public void | ||
| onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) { | ||
| nativeOnCharacteristicReadRequest(nativePointer, device, requestId, offset, characteristic); | ||
| } | ||
| @Override | ||
| public void | ||
| onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { | ||
| nativeOnCharacteristicWriteRequest(nativePointer, device, requestId, characteristic, preparedWrite, responseNeeded, offset, value); | ||
| } | ||
| @Override | ||
| public void | ||
| onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) { | ||
| nativeOnDescriptorWriteRequest(nativePointer, device, requestId, descriptor, preparedWrite, responseNeeded, offset, value); | ||
| } | ||
| @Override | ||
| public void | ||
| onNotificationSent(BluetoothDevice device, int status) { | ||
| nativeOnNotificationSent(nativePointer, device, status); | ||
| } | ||
| private static native void | ||
| nativeOnConnectionStateChange(long nativePointer, BluetoothDevice device, int status, int newState); | ||
| private static native void | ||
| nativeOnServiceAdded(long nativePointer, int status, BluetoothGattService service); | ||
| private static native void | ||
| nativeOnCharacteristicReadRequest(long nativePointer, BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic); | ||
| private static native void | ||
| nativeOnCharacteristicWriteRequest(long nativePointer, BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value); | ||
| private static native void | ||
| nativeOnDescriptorWriteRequest(long nativePointer, BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value); | ||
| private static native void | ||
| nativeOnNotificationSent(long nativePointer, BluetoothDevice device, int status); | ||
| } |
| import { EventEmitter, EventMap } from 'bare-events' | ||
| import Service from './service' | ||
| import Characteristic from './characteristic' | ||
| import L2CAPChannel from './channel' | ||
| export interface PeripheralOptions { | ||
| connectHandle?: ArrayBuffer | ||
| id?: string | ||
| name?: string | ||
| } | ||
| export interface PeripheralEventMap extends EventMap { | ||
| servicesDiscover: [services: Service[] | null, error?: string] | ||
| characteristicsDiscover: [ | ||
| service: string, | ||
| characteristics: Characteristic[] | null, | ||
| error?: string | ||
| ] | ||
| read: [characteristic: string, data: Uint8Array, error?: string] | ||
| write: [characteristic: string, error?: string] | ||
| notify: [characteristic: string, data: Uint8Array, error?: string] | ||
| notifyState: [characteristic: string, isNotifying: boolean, error?: string] | ||
| channelOpen: [channel: L2CAPChannel | null, error?: string] | ||
| mtuChanged: [mtu: number, error?: string] | ||
| } | ||
| export default class Peripheral extends EventEmitter<PeripheralEventMap> { | ||
| constructor(peripheralHandle: ArrayBuffer, opts?: PeripheralOptions) | ||
| readonly id: string | ||
| readonly name: string | null | ||
| discoverServices(): void | ||
| discoverCharacteristics(service: string): void | ||
| read(characteristic: string): void | ||
| write(characteristic: string, data: Uint8Array, withResponse?: boolean): void | ||
| subscribe(characteristic: string): void | ||
| unsubscribe(characteristic: string): void | ||
| openL2CAPChannel(psm: number): void | ||
| requestMtu(mtu: number): void | ||
| destroy(): void | ||
| static readonly PROPERTY_READ: number | ||
| static readonly PROPERTY_WRITE_WITHOUT_RESPONSE: number | ||
| static readonly PROPERTY_WRITE: number | ||
| static readonly PROPERTY_NOTIFY: number | ||
| static readonly PROPERTY_INDICATE: number | ||
| } |
| const EventEmitter = require('bare-events') | ||
| const binding = require('../binding') | ||
| const Service = require('./service') | ||
| const Characteristic = require('./characteristic') | ||
| const L2CAPChannel = require('./channel') | ||
| module.exports = exports = class Peripheral extends EventEmitter { | ||
| constructor(peripheralHandle, opts = {}) { | ||
| super() | ||
| this._peripheralHandle = peripheralHandle | ||
| this._connectHandle = opts.connectHandle || null | ||
| this._id = opts.id || null | ||
| this._name = opts.name === undefined ? null : opts.name | ||
| this._destroyed = false | ||
| this._services = new Map() | ||
| this._characteristics = new Map() | ||
| this._characteristicsByHandle = new Map() | ||
| this._handle = binding.peripheralInit( | ||
| peripheralHandle, | ||
| this, | ||
| this._onservicesdiscover, | ||
| this._oncharacteristicsdiscover, | ||
| this._onread, | ||
| this._onwrite, | ||
| this._onnotify, | ||
| this._onnotifystate, | ||
| this._onchannelopen, | ||
| this._onmtuchanged | ||
| ) | ||
| if (this._id === null) this._id = binding.peripheralId(this._handle) | ||
| if (opts.name === undefined) this._name = binding.peripheralName(this._handle) | ||
| } | ||
| get id() { | ||
| return this._id | ||
| } | ||
| get name() { | ||
| return this._name | ||
| } | ||
| discoverServices() { | ||
| return binding.peripheralDiscoverServices(this._handle) | ||
| } | ||
| discoverCharacteristics(service) { | ||
| binding.peripheralDiscoverCharacteristics(this._handle, service._handle) | ||
| } | ||
| read(characteristic) { | ||
| return binding.peripheralRead(this._handle, characteristic._handle) | ||
| } | ||
| write(characteristic, data, withResponse) { | ||
| if (withResponse === undefined) withResponse = true | ||
| return binding.peripheralWrite(this._handle, characteristic._handle, data, withResponse) | ||
| } | ||
| subscribe(characteristic) { | ||
| return binding.peripheralSubscribe(this._handle, characteristic._handle) | ||
| } | ||
| unsubscribe(characteristic) { | ||
| return binding.peripheralUnsubscribe(this._handle, characteristic._handle) | ||
| } | ||
| openL2CAPChannel(psm) { | ||
| binding.peripheralOpenL2CAPChannel(this._handle, psm) | ||
| } | ||
| requestMtu(mtu) { | ||
| return binding.peripheralRequestMtu(this._handle, mtu) | ||
| } | ||
| destroy() { | ||
| if (this._destroyed) return | ||
| this._destroyed = true | ||
| this._connectHandle = null | ||
| binding.peripheralDestroy(this._handle) | ||
| } | ||
| [Symbol.for('bare.inspect')]() { | ||
| return { | ||
| __proto__: { constructor: Peripheral }, | ||
| id: this.id, | ||
| name: this.name | ||
| } | ||
| } | ||
| _onservicesdiscover(count, error) { | ||
| if (error) { | ||
| this.emit('servicesDiscover', null, error) | ||
| return | ||
| } | ||
| const services = [] | ||
| for (let i = 0; i < count; i++) { | ||
| const handle = binding.peripheralServiceAtIndex(this._handle, i) | ||
| const serviceKey = binding.serviceKey(handle) | ||
| const uuid = binding.serviceUuid(handle) | ||
| let service = this._services.get(serviceKey) | ||
| if (!service) { | ||
| service = new Service(uuid) | ||
| service._handle = handle | ||
| service._key = serviceKey | ||
| this._services.set(serviceKey, service) | ||
| } else { | ||
| service._handle = handle | ||
| } | ||
| services.push(service) | ||
| } | ||
| this.emit('servicesDiscover', services, null) | ||
| } | ||
| _oncharacteristicsdiscover(serviceHandle, count, error) { | ||
| const serviceKey = binding.serviceKey(serviceHandle) | ||
| const service = this._services.get(serviceKey) || null | ||
| if (error) { | ||
| this.emit('characteristicsDiscover', service, null, error) | ||
| return | ||
| } | ||
| const characteristics = [] | ||
| for (let i = 0; i < count; i++) { | ||
| const handle = binding.serviceCharacteristicAtIndex(serviceHandle, i) | ||
| const handleKey = binding.characteristicKey(handle) | ||
| const characteristicKey = serviceKey + ':' + handleKey | ||
| const uuid = binding.characteristicUuid(handle) | ||
| const properties = binding.characteristicProperties(handle) | ||
| let characteristic = this._characteristics.get(characteristicKey) | ||
| if (!characteristic) { | ||
| characteristic = new Characteristic(uuid) | ||
| characteristic._handle = handle | ||
| characteristic._properties = properties | ||
| characteristic._key = characteristicKey | ||
| characteristic._serviceKey = serviceKey | ||
| characteristic._handleKey = handleKey | ||
| this._characteristics.set(characteristicKey, characteristic) | ||
| } else { | ||
| characteristic._handle = handle | ||
| characteristic._properties = properties | ||
| } | ||
| this._characteristicsByHandle.set(handleKey, characteristic) | ||
| characteristics.push(characteristic) | ||
| } | ||
| if (service) { | ||
| service._characteristics = characteristics | ||
| } | ||
| this.emit('characteristicsDiscover', service, characteristics, null) | ||
| } | ||
| _onread(charHandle, uuid, data, error) { | ||
| const characteristic = | ||
| this._characteristicsByHandle.get(binding.characteristicKey(charHandle)) || null | ||
| this.emit('read', characteristic, data, error) | ||
| } | ||
| _onwrite(charHandle, uuid, error) { | ||
| const characteristic = | ||
| this._characteristicsByHandle.get(binding.characteristicKey(charHandle)) || null | ||
| this.emit('write', characteristic, error) | ||
| } | ||
| _onnotify(uuid, data, error) { | ||
| const characteristic = this._characteristicsByHandle.get(uuid) || null | ||
| this.emit('notify', characteristic, data, error) | ||
| } | ||
| _onnotifystate(charHandle, uuid, isNotifying, error) { | ||
| const characteristic = | ||
| this._characteristicsByHandle.get(binding.characteristicKey(charHandle)) || null | ||
| this.emit('notifyState', characteristic, isNotifying, error) | ||
| } | ||
| _ondisconnect() { | ||
| this._connectHandle = null | ||
| } | ||
| _onchannelopen(channelHandle, error) { | ||
| if (error || !channelHandle) { | ||
| this.emit('channelOpen', null, error) | ||
| return | ||
| } | ||
| const channel = new L2CAPChannel(channelHandle) | ||
| this.emit('channelOpen', channel, null) | ||
| } | ||
| _onmtuchanged(mtu, error) { | ||
| this.emit('mtuChanged', mtu, error) | ||
| } | ||
| } | ||
| exports.PROPERTY_READ = binding.PROPERTY_READ | ||
| exports.PROPERTY_WRITE_WITHOUT_RESPONSE = binding.PROPERTY_WRITE_WITHOUT_RESPONSE | ||
| exports.PROPERTY_WRITE = binding.PROPERTY_WRITE | ||
| exports.PROPERTY_NOTIFY = binding.PROPERTY_NOTIFY | ||
| exports.PROPERTY_INDICATE = binding.PROPERTY_INDICATE |
| package to.holepunch.bare.bluetooth; | ||
| import android.bluetooth.le.ScanResult; | ||
| public final class ScanCallback extends android.bluetooth.le.ScanCallback { | ||
| private final long nativePointer; | ||
| public ScanCallback(long nativePointer) { | ||
| this.nativePointer = nativePointer; | ||
| } | ||
| @Override | ||
| public void | ||
| onScanResult(int callbackType, ScanResult result) { | ||
| nativeOnScanResult(nativePointer, callbackType, result); | ||
| } | ||
| @Override | ||
| public void | ||
| onScanFailed(int errorCode) { | ||
| nativeOnScanFailed(nativePointer, errorCode); | ||
| } | ||
| private static native void | ||
| nativeOnScanResult(long nativePointer, int callbackType, ScanResult result); | ||
| private static native void | ||
| nativeOnScanFailed(long nativePointer, int errorCode); | ||
| } |
| import { EventEmitter, EventMap } from 'bare-events' | ||
| import Service from './service' | ||
| import Characteristic from './characteristic' | ||
| import L2CAPChannel from './channel' | ||
| export type BluetoothState = 'off' | 'turningOn' | 'on' | 'turningOff' | ||
| export interface AdvertisingOptions { | ||
| name?: string | ||
| serviceUUIDs?: string[] | ||
| } | ||
| export interface ChannelOptions { | ||
| encrypted?: boolean | ||
| } | ||
| export interface ReadRequest { | ||
| characteristicUuid: string | ||
| offset: number | ||
| } | ||
| export interface WriteRequest { | ||
| characteristicUuid: string | ||
| data: Uint8Array | ||
| } | ||
| export interface ServerEventMap extends EventMap { | ||
| stateChange: [state: BluetoothState] | ||
| addService: [uuid: string, error?: string] | ||
| channelPublish: [psm: number, error?: string] | ||
| channelOpen: [channel: L2CAPChannel | null, error?: string] | ||
| readRequest: [request: ReadRequest] | ||
| writeRequests: [requests: WriteRequest[]] | ||
| subscribe: [deviceAddress: string, characteristicUuid: string] | ||
| unsubscribe: [deviceAddress: string, characteristicUuid: string] | ||
| advertiseError: [errorCode: number, error: string] | ||
| } | ||
| declare class Server extends EventEmitter<ServerEventMap> { | ||
| constructor() | ||
| readonly state: BluetoothState | ||
| addService(service: Service): void | ||
| startAdvertising(opts?: AdvertisingOptions): void | ||
| stopAdvertising(): void | ||
| respondToRequest(request: ReadRequest, result: number, data?: Uint8Array | null): void | ||
| updateValue(characteristic: Characteristic, data: Uint8Array): boolean | ||
| publishChannel(opts?: ChannelOptions): void | ||
| unpublishChannel(psm: number): void | ||
| destroy(): void | ||
| static readonly STATE_OFF: number | ||
| static readonly STATE_TURNING_ON: number | ||
| static readonly STATE_ON: number | ||
| static readonly STATE_TURNING_OFF: number | ||
| static readonly PROPERTY_READ: number | ||
| static readonly PROPERTY_WRITE_WITHOUT_RESPONSE: number | ||
| static readonly PROPERTY_WRITE: number | ||
| static readonly PROPERTY_NOTIFY: number | ||
| static readonly PROPERTY_INDICATE: number | ||
| static readonly PERMISSION_READABLE: number | ||
| static readonly PERMISSION_WRITEABLE: number | ||
| static readonly PERMISSION_READ_ENCRYPTED: number | ||
| static readonly PERMISSION_WRITE_ENCRYPTED: number | ||
| static readonly ATT_SUCCESS: number | ||
| static readonly ATT_INVALID_HANDLE: number | ||
| static readonly ATT_READ_NOT_PERMITTED: number | ||
| static readonly ATT_WRITE_NOT_PERMITTED: number | ||
| static readonly ATT_INSUFFICIENT_RESOURCES: number | ||
| static readonly ATT_UNLIKELY_ERROR: number | ||
| } | ||
| export default Server |
+197
| const EventEmitter = require('bare-events') | ||
| const binding = require('../binding') | ||
| const L2CAPChannel = require('./channel') | ||
| const STATES = { | ||
| [binding.STATE_OFF]: 'off', | ||
| [binding.STATE_TURNING_ON]: 'turningOn', | ||
| [binding.STATE_ON]: 'on', | ||
| [binding.STATE_TURNING_OFF]: 'turningOff' | ||
| } | ||
| module.exports = exports = class Server extends EventEmitter { | ||
| constructor() { | ||
| super() | ||
| this._state = 'off' | ||
| this._handle = binding.serverInit( | ||
| this, | ||
| this._onstatechange, | ||
| this._onaddservice, | ||
| this._onreadrequest, | ||
| this._onwriterequest, | ||
| this._onsubscribe, | ||
| this._onunsubscribe, | ||
| this._onadvertiseerror, | ||
| this._onchannelpublish, | ||
| this._onchannelopen, | ||
| this._onnotifysent | ||
| ) | ||
| } | ||
| get state() { | ||
| return this._state | ||
| } | ||
| addService(service) { | ||
| const charHandles = [] | ||
| for (const char of service.characteristics) { | ||
| let permissions = char.permissions | ||
| if (permissions === null) { | ||
| permissions = 0 | ||
| if (char.properties & exports.PROPERTY_READ) { | ||
| permissions |= exports.PERMISSION_READABLE | ||
| } | ||
| if (char.properties & (exports.PROPERTY_WRITE | exports.PROPERTY_WRITE_WITHOUT_RESPONSE)) { | ||
| permissions |= exports.PERMISSION_WRITEABLE | ||
| } | ||
| } | ||
| const uuid = binding.createUUID(char.uuid) | ||
| char._handle = binding.createMutableCharacteristic( | ||
| uuid, | ||
| char.properties, | ||
| permissions, | ||
| char.value || null | ||
| ) | ||
| charHandles.push(char._handle) | ||
| } | ||
| const serviceUuid = binding.createUUID(service.uuid) | ||
| const serviceHandle = binding.createMutableService(serviceUuid, service.primary) | ||
| binding.serviceSetCharacteristics(serviceHandle, charHandles) | ||
| binding.serverAddService(this._handle, serviceHandle) | ||
| } | ||
| startAdvertising(opts = {}) { | ||
| const uuids = opts.serviceUUIDs ? opts.serviceUUIDs.map((s) => binding.createUUID(s)) : null | ||
| binding.serverStartAdvertising(this._handle, opts.name || null, uuids) | ||
| } | ||
| stopAdvertising() { | ||
| binding.serverStopAdvertising(this._handle) | ||
| } | ||
| respondToRequest(request, result, data) { | ||
| binding.serverRespondToRequest( | ||
| this._handle, | ||
| request.handle, | ||
| request.requestId, | ||
| result, | ||
| request.offset, | ||
| data || null | ||
| ) | ||
| } | ||
| updateValue(characteristic, data) { | ||
| return binding.serverUpdateValue(this._handle, characteristic._handle, data) | ||
| } | ||
| publishChannel(opts = {}) { | ||
| binding.serverPublishChannel(this._handle, opts.encrypted || false) | ||
| } | ||
| unpublishChannel(psm) { | ||
| binding.serverUnpublishChannel(this._handle, psm) | ||
| } | ||
| destroy() { | ||
| binding.serverDestroy(this._handle) | ||
| } | ||
| [Symbol.for('bare.inspect')]() { | ||
| return { | ||
| __proto__: { constructor: Server }, | ||
| state: this._state | ||
| } | ||
| } | ||
| _onstatechange(state) { | ||
| this._state = STATES[state] || 'off' | ||
| this.emit('stateChange', this._state) | ||
| } | ||
| _onaddservice(uuid, error) { | ||
| this.emit('serviceAdd', uuid, error) | ||
| } | ||
| _onreadrequest(requestHandle, requestId, characteristicUuid, offset) { | ||
| this.emit('readRequest', { | ||
| handle: requestHandle, | ||
| requestId, | ||
| characteristicUuid, | ||
| offset | ||
| }) | ||
| } | ||
| _onwriterequest(requestHandle, requestId, characteristicUuid, offset, data, responseNeeded) { | ||
| this.emit('writeRequest', [ | ||
| { | ||
| handle: requestHandle, | ||
| requestId, | ||
| characteristicUuid, | ||
| data, | ||
| offset, | ||
| responseNeeded | ||
| } | ||
| ]) | ||
| } | ||
| _onsubscribe(deviceAddress, characteristicUuid) { | ||
| this.emit('subscribe', deviceAddress, characteristicUuid) | ||
| } | ||
| _onunsubscribe(deviceAddress, characteristicUuid) { | ||
| this.emit('unsubscribe', deviceAddress, characteristicUuid) | ||
| } | ||
| _onadvertiseerror(errorCode, error) { | ||
| this.emit('advertiseError', errorCode, error) | ||
| } | ||
| _onchannelpublish(psm, error) { | ||
| this.emit('channelPublish', psm, error) | ||
| } | ||
| _onchannelopen(channelHandle, error) { | ||
| if (error || !channelHandle) { | ||
| this.emit('channelOpen', null, error) | ||
| return | ||
| } | ||
| const channel = new L2CAPChannel(channelHandle) | ||
| this.emit('channelOpen', channel, null) | ||
| } | ||
| _onnotifysent(deviceAddress, status) { | ||
| this.emit('notifySent', deviceAddress, status) | ||
| } | ||
| } | ||
| exports.STATE_OFF = binding.STATE_OFF | ||
| exports.STATE_TURNING_ON = binding.STATE_TURNING_ON | ||
| exports.STATE_ON = binding.STATE_ON | ||
| exports.STATE_TURNING_OFF = binding.STATE_TURNING_OFF | ||
| exports.PROPERTY_READ = binding.PROPERTY_READ | ||
| exports.PROPERTY_WRITE_WITHOUT_RESPONSE = binding.PROPERTY_WRITE_WITHOUT_RESPONSE | ||
| exports.PROPERTY_WRITE = binding.PROPERTY_WRITE | ||
| exports.PROPERTY_NOTIFY = binding.PROPERTY_NOTIFY | ||
| exports.PROPERTY_INDICATE = binding.PROPERTY_INDICATE | ||
| exports.PERMISSION_READABLE = binding.PERMISSION_READABLE | ||
| exports.PERMISSION_WRITEABLE = binding.PERMISSION_WRITEABLE | ||
| exports.PERMISSION_READ_ENCRYPTED = binding.PERMISSION_READ_ENCRYPTED | ||
| exports.PERMISSION_WRITE_ENCRYPTED = binding.PERMISSION_WRITE_ENCRYPTED | ||
| exports.ATT_SUCCESS = binding.ATT_SUCCESS | ||
| exports.ATT_INVALID_HANDLE = binding.ATT_INVALID_HANDLE | ||
| exports.ATT_READ_NOT_PERMITTED = binding.ATT_READ_NOT_PERMITTED | ||
| exports.ATT_WRITE_NOT_PERMITTED = binding.ATT_WRITE_NOT_PERMITTED | ||
| exports.ATT_INSUFFICIENT_RESOURCES = binding.ATT_INSUFFICIENT_RESOURCES | ||
| exports.ATT_UNLIKELY_ERROR = binding.ATT_UNLIKELY_ERROR |
| import Characteristic from './characteristic' | ||
| export default class Service { | ||
| constructor(uuid: string, characteristics?: Characteristic[], opts?: ServiceOptions) | ||
| readonly uuid: string | ||
| readonly characteristics: Characteristic[] | ||
| readonly primary: boolean | ||
| } | ||
| export interface ServiceOptions { | ||
| primary?: boolean | ||
| } |
| module.exports = class Service { | ||
| constructor(uuid, characteristics, opts = {}) { | ||
| this._uuid = uuid | ||
| this._characteristics = characteristics || [] | ||
| this._primary = opts.primary !== false | ||
| this._handle = null | ||
| } | ||
| get uuid() { | ||
| return this._uuid | ||
| } | ||
| get characteristics() { | ||
| return this._characteristics | ||
| } | ||
| get primary() { | ||
| return this._primary | ||
| } | ||
| [Symbol.for('bare.inspect')]() { | ||
| return { | ||
| __proto__: { constructor: Service }, | ||
| uuid: this._uuid | ||
| } | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
+432
| # bare-bluetooth-android | ||
| Android Bluetooth Low Energy (BLE) bindings for Bare, providing both central and peripheral roles. Built on the Android Bluetooth API. | ||
| ``` | ||
| npm i bare-bluetooth-android | ||
| ``` | ||
| ## Usage | ||
| ```js | ||
| const { Central } = require('bare-bluetooth-android') | ||
| const central = new Central() | ||
| central.on('stateChange', (state) => { | ||
| if (state === 'on') { | ||
| central.startScan(['180D']) // Heart Rate service UUID | ||
| } | ||
| }) | ||
| central.on('discover', (peripheral) => { | ||
| console.log('Found:', peripheral.name, peripheral.id) | ||
| central.stopScan() | ||
| central.connect(peripheral) | ||
| }) | ||
| central.on('connect', (peripheral) => { | ||
| peripheral.discoverServices() | ||
| peripheral.on('servicesDiscover', (services) => { | ||
| // Discover characteristics for each service | ||
| }) | ||
| }) | ||
| ``` | ||
| ## API | ||
| #### `const central = new Central()` | ||
| Create a new BLE central manager for scanning and connecting to peripherals. | ||
| #### `central.state` | ||
| The current Bluetooth adapter state. One of `'off'`, `'turningOn'`, `'on'`, or `'turningOff'`. | ||
| #### `central.startScan(serviceUUIDs[, opts])` | ||
| Start scanning for peripherals advertising the given `serviceUUIDs`. Pass `null` to scan for all peripherals. | ||
| Options include: | ||
| ```js | ||
| opts = { | ||
| scanMode: null | ||
| } | ||
| ``` | ||
| Set `scanMode` to one of `Central.SCAN_MODE_OPPORTUNISTIC`, `Central.SCAN_MODE_LOW_POWER`, `Central.SCAN_MODE_BALANCED`, or `Central.SCAN_MODE_LOW_LATENCY`. | ||
| #### `central.stopScan()` | ||
| Stop scanning for peripherals. | ||
| #### `central.connect(peripheral)` | ||
| Connect to a discovered `peripheral`. | ||
| #### `central.disconnect(peripheral)` | ||
| Disconnect from a connected `peripheral`. | ||
| #### `central.destroy()` | ||
| Destroy the central manager, disconnecting all connected peripherals. | ||
| #### `event: 'stateChange'` | ||
| Emitted when the Bluetooth adapter state changes. The listener receives the new `state` string. | ||
| #### `event: 'discover'` | ||
| Emitted when a peripheral is discovered during scanning. The listener receives a `peripheral` object with `handle`, `id`, `name`, and `rssi` properties. | ||
| #### `event: 'connect'` | ||
| Emitted when a connection to a peripheral is established. The listener receives a `Peripheral` instance. | ||
| #### `event: 'disconnect'` | ||
| Emitted when a peripheral disconnects. The listener receives the `peripheral` and an optional `error`. | ||
| #### `event: 'connectFail'` | ||
| Emitted when a connection attempt fails. The listener receives the peripheral `id` and an `error`. | ||
| #### `event: 'scanFail'` | ||
| Emitted when scanning fails. The listener receives the `errorCode`. | ||
| #### `Central.SCAN_MODE_OPPORTUNISTIC` | ||
| #### `Central.SCAN_MODE_LOW_POWER` | ||
| #### `Central.SCAN_MODE_BALANCED` | ||
| #### `Central.SCAN_MODE_LOW_LATENCY` | ||
| Scan mode constants for use with `central.startScan()`. | ||
| #### `const peripheral = new Peripheral(peripheralHandle[, opts])` | ||
| Create a new peripheral instance. Typically obtained via the `'connect'` event on `Central` rather than constructed directly. | ||
| Options include: | ||
| ```js | ||
| opts = { | ||
| connectHandle: null, | ||
| id: null, | ||
| name: null | ||
| } | ||
| ``` | ||
| #### `peripheral.id` | ||
| The unique identifier of the peripheral. | ||
| #### `peripheral.name` | ||
| The advertised name of the peripheral, or `null` if unavailable. | ||
| #### `peripheral.discoverServices()` | ||
| Discover services offered by the peripheral. Results are emitted via the `'servicesDiscover'` event. | ||
| #### `peripheral.discoverCharacteristics(service)` | ||
| Discover characteristics for the given `service`. Results are emitted via the `'characteristicsDiscover'` event. | ||
| #### `peripheral.read(characteristic)` | ||
| Read the value of `characteristic`. The result is emitted via the `'read'` event. | ||
| #### `peripheral.write(characteristic, data[, withResponse])` | ||
| Write `data` to `characteristic`. If `withResponse` is `true` (the default), a write confirmation is requested. | ||
| #### `peripheral.subscribe(characteristic)` | ||
| Subscribe to notifications for `characteristic`. | ||
| #### `peripheral.unsubscribe(characteristic)` | ||
| Unsubscribe from notifications for `characteristic`. | ||
| #### `peripheral.openL2CAPChannel(psm)` | ||
| Open an L2CAP channel to the peripheral using the given `psm`. The result is emitted via the `'channelOpen'` event. | ||
| #### `peripheral.requestMtu(mtu)` | ||
| Request a new MTU size. The result is emitted via the `'mtuChanged'` event. | ||
| #### `peripheral.destroy()` | ||
| Destroy the peripheral instance. | ||
| #### `event: 'servicesDiscover'` | ||
| Emitted when services are discovered. The listener receives an array of `Service` instances and an optional `error`. | ||
| #### `event: 'characteristicsDiscover'` | ||
| Emitted when characteristics are discovered. The listener receives the `service`, an array of `Characteristic` instances, and an optional `error`. | ||
| #### `event: 'read'` | ||
| Emitted when a characteristic read completes. The listener receives the `characteristic`, `data`, and an optional `error`. | ||
| #### `event: 'write'` | ||
| Emitted when a characteristic write completes. The listener receives the `characteristic` and an optional `error`. | ||
| #### `event: 'notify'` | ||
| Emitted when a characteristic notification is received. The listener receives the `characteristic`, `data`, and an optional `error`. | ||
| #### `event: 'notifyState'` | ||
| Emitted when the notification state changes. The listener receives the `characteristic`, `isNotifying`, and an optional `error`. | ||
| #### `event: 'channelOpen'` | ||
| Emitted when an L2CAP channel is opened. The listener receives an `L2CAPChannel` instance or `null`, and an optional `error`. | ||
| #### `event: 'mtuChanged'` | ||
| Emitted when the MTU is changed. The listener receives the new `mtu` and an optional `error`. | ||
| #### `Peripheral.PROPERTY_READ` | ||
| #### `Peripheral.PROPERTY_WRITE_WITHOUT_RESPONSE` | ||
| #### `Peripheral.PROPERTY_WRITE` | ||
| #### `Peripheral.PROPERTY_NOTIFY` | ||
| #### `Peripheral.PROPERTY_INDICATE` | ||
| Characteristic property constants. | ||
| #### `const server = new Server()` | ||
| Create a new BLE peripheral server for advertising services and handling client requests. | ||
| #### `server.state` | ||
| The current Bluetooth adapter state. One of `'off'`, `'turningOn'`, `'on'`, or `'turningOff'`. | ||
| #### `server.addService(service)` | ||
| Add a `service` to the GATT server. The `'serviceAdd'` event is emitted when the service has been registered. | ||
| #### `server.startAdvertising([opts])` | ||
| Start advertising the server. | ||
| Options include: | ||
| ```js | ||
| opts = { | ||
| name: null, | ||
| serviceUUIDs: null | ||
| } | ||
| ``` | ||
| #### `server.stopAdvertising()` | ||
| Stop advertising. | ||
| #### `server.respondToRequest(request, result[, data])` | ||
| Respond to a read or write `request` with a `result` code and optional `data`. Use the `Server.ATT_*` constants for the result. | ||
| #### `server.updateValue(characteristic, data)` | ||
| Update the value of `characteristic` with `data` and notify subscribed clients. Returns `true` if the notification was sent successfully. | ||
| #### `server.publishChannel([opts])` | ||
| Publish an L2CAP channel. The `'channelPublish'` event is emitted with the assigned PSM. | ||
| Options include: | ||
| ```js | ||
| opts = { | ||
| encrypted: false | ||
| } | ||
| ``` | ||
| #### `server.unpublishChannel(psm)` | ||
| Unpublish an L2CAP channel with the given `psm`. | ||
| #### `server.destroy()` | ||
| Destroy the server. | ||
| #### `event: 'stateChange'` | ||
| Emitted when the Bluetooth adapter state changes. The listener receives the new `state` string. | ||
| #### `event: 'serviceAdd'` | ||
| Emitted when a service is added. The listener receives the `uuid` and an optional `error`. | ||
| #### `event: 'readRequest'` | ||
| Emitted when a client reads a characteristic. The listener receives a `request` object with `handle`, `requestId`, `characteristicUuid`, and `offset` properties. | ||
| #### `event: 'writeRequest'` | ||
| Emitted when a client writes to a characteristic. The listener receives an array of request objects, each with `handle`, `requestId`, `characteristicUuid`, `data`, `offset`, and `responseNeeded` properties. | ||
| #### `event: 'subscribe'` | ||
| Emitted when a client subscribes to notifications. The listener receives `deviceAddress` and `characteristicUuid`. | ||
| #### `event: 'unsubscribe'` | ||
| Emitted when a client unsubscribes from notifications. The listener receives `deviceAddress` and `characteristicUuid`. | ||
| #### `event: 'advertiseError'` | ||
| Emitted when advertising fails. The listener receives `errorCode` and `error`. | ||
| #### `event: 'channelPublish'` | ||
| Emitted when an L2CAP channel is published. The listener receives the `psm` and an optional `error`. | ||
| #### `event: 'channelOpen'` | ||
| Emitted when an L2CAP channel is opened by a client. The listener receives an `L2CAPChannel` instance or `null`, and an optional `error`. | ||
| #### `event: 'notifySent'` | ||
| Emitted when a notification is delivered. The listener receives `deviceAddress` and `status`. | ||
| #### `Server.PROPERTY_READ` | ||
| #### `Server.PROPERTY_WRITE_WITHOUT_RESPONSE` | ||
| #### `Server.PROPERTY_WRITE` | ||
| #### `Server.PROPERTY_NOTIFY` | ||
| #### `Server.PROPERTY_INDICATE` | ||
| Characteristic property constants. | ||
| #### `Server.PERMISSION_READABLE` | ||
| #### `Server.PERMISSION_WRITEABLE` | ||
| #### `Server.PERMISSION_READ_ENCRYPTED` | ||
| #### `Server.PERMISSION_WRITE_ENCRYPTED` | ||
| Characteristic permission constants. | ||
| #### `Server.ATT_SUCCESS` | ||
| #### `Server.ATT_INVALID_HANDLE` | ||
| #### `Server.ATT_READ_NOT_PERMITTED` | ||
| #### `Server.ATT_WRITE_NOT_PERMITTED` | ||
| #### `Server.ATT_INSUFFICIENT_RESOURCES` | ||
| #### `Server.ATT_UNLIKELY_ERROR` | ||
| ATT result codes for use with `server.respondToRequest()`. | ||
| #### `const channel = new L2CAPChannel(channelHandle)` | ||
| A duplex stream representing an L2CAP connection-oriented channel. Extends `Duplex` from <https://github.com/holepunchto/bare-stream>. Typically obtained via the `'channelOpen'` event rather than constructed directly. | ||
| #### `channel.psm` | ||
| The Protocol/Service Multiplexer number of the channel. | ||
| #### `channel.peer` | ||
| The address of the remote peer, or `null`. | ||
| #### `const service = new Service(uuid[, characteristics][, opts])` | ||
| Create a new GATT service definition. | ||
| Options include: | ||
| ```js | ||
| opts = { | ||
| primary: true | ||
| } | ||
| ``` | ||
| #### `service.uuid` | ||
| The UUID of the service. | ||
| #### `service.characteristics` | ||
| The array of characteristics belonging to the service. | ||
| #### `service.primary` | ||
| Whether the service is a primary service. | ||
| #### `const characteristic = new Characteristic(uuid[, opts])` | ||
| Create a new GATT characteristic definition. | ||
| Options include: | ||
| ```js | ||
| opts = { | ||
| read: false, | ||
| write: false, | ||
| writeWithoutResponse: false, | ||
| notify: false, | ||
| indicate: false, | ||
| permissions: null, | ||
| value: null | ||
| } | ||
| ``` | ||
| Set `read`, `write`, `writeWithoutResponse`, `notify`, and `indicate` to configure the characteristic properties. If `permissions` is `null`, permissions are inferred from the properties. | ||
| #### `characteristic.uuid` | ||
| The UUID of the characteristic. | ||
| #### `characteristic.properties` | ||
| The property flags of the characteristic. | ||
| #### `characteristic.permissions` | ||
| The permission flags of the characteristic, or `null` if inferred. | ||
| #### `characteristic.value` | ||
| The current value of the characteristic, or `null`. | ||
| #### `Characteristic.PROPERTY_READ` | ||
| #### `Characteristic.PROPERTY_WRITE_WITHOUT_RESPONSE` | ||
| #### `Characteristic.PROPERTY_WRITE` | ||
| #### `Characteristic.PROPERTY_NOTIFY` | ||
| #### `Characteristic.PROPERTY_INDICATE` | ||
| Characteristic property constants. | ||
| ## License | ||
| Apache-2.0 |
+51
-1
@@ -1,1 +0,51 @@ | ||
| {"name":"bare-bluetooth-android","version":"0.0.0"} | ||
| { | ||
| "name": "bare-bluetooth-android", | ||
| "version": "0.1.0", | ||
| "description": "Android Bluetooth bindings for Bare", | ||
| "addon": true, | ||
| "scripts": { | ||
| "format": "prettier --write . && lunte --fix", | ||
| "lint": "prettier --check . && lunte", | ||
| "test": "brittle-bare --coverage test.js" | ||
| }, | ||
| "exports": { | ||
| "./package": "./package.json", | ||
| ".": { | ||
| "types": "./index.d.ts", | ||
| "default": "./index.js" | ||
| } | ||
| }, | ||
| "files": [ | ||
| "index.js", | ||
| "index.d.ts", | ||
| "binding.cc", | ||
| "binding.js", | ||
| "CMakeLists.txt", | ||
| "lib", | ||
| "prebuilds" | ||
| ], | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/holepunchto/bare-bluetooth-android.git" | ||
| }, | ||
| "author": "Holepunch", | ||
| "license": "Apache-2.0", | ||
| "bugs": { | ||
| "url": "https://github.com/holepunchto/bare-bluetooth-android/issues" | ||
| }, | ||
| "homepage": "https://github.com/holepunchto/bare-bluetooth-android#readme", | ||
| "dependencies": { | ||
| "bare-events": "^2.8.2", | ||
| "bare-stream": "^2.11.0" | ||
| }, | ||
| "devDependencies": { | ||
| "bare-os": "^3.8.0", | ||
| "brittle": "^3.19.1", | ||
| "cmake-android": "^0.1.2", | ||
| "cmake-bare": "^1.6.5", | ||
| "cmake-fetch": "^1.4.0", | ||
| "lunte": "^1.6.0", | ||
| "prettier": "^3.8.1", | ||
| "prettier-config-holepunch": "^2.0.0" | ||
| } | ||
| } |
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Empty package
Supply chain riskPackage does not contain any code. It may be removed, is name squatting, or the result of a faulty package publish.
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
No License Found
LicenseLicense information could not be found.
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
No website
QualityPackage does not have a website.
3189586
6253990.2%31
3000%0
-100%914
Infinity%0
-100%1
-50%0
-100%433
Infinity%0
-100%2
Infinity%8
Infinity%5
400%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added