import { EventDispatcher , TypedDispatcher } from "./dispatcher" ; import { BluetoothRemoteGATTService } from "./service" ; import { BluetoothRemoteGATTDescriptor } from "./descriptor" ; import { getDescriptorUUID } from "./helpers" ; import { adapter } from "./adapter" ; import { W3CBluetoothRemoteGATTCharacteristic } from "./interfaces" ; import { DOMEvent } from "./events" ; hidden export interface BluetoothRemoteGATTCharacteristicEvents { /**
     * Characteristic value changed event
     */ characteristicvaluechanged : Event ; } /**
 * Bluetooth Remote GATT Characteristic class
 */ export class BluetoothRemoteGATTCharacteristic extends ( EventDispatcher as new ( ) => TypedDispatcher < BluetoothRemoteGATTCharacteristicEvents > ) implements W3CBluetoothRemoteGATTCharacteristic { /**
     * The service the characteristic is related to
     */ public readonly service : BluetoothRemoteGATTService = null ; /**
     * The unique identifier of the characteristic
     */ public readonly uuid = null ; /**
     * The properties of the characteristic
     */ public readonly properties : BluetoothCharacteristicProperties ; private _value : DataView = null ; /**
     * The value of the characteristic
     */ public get value ( ) : DataView { return this . _value ; } private handle : string = null ; private descriptors : Array < BluetoothRemoteGATTDescriptor > = null ; private _oncharacteristicvaluechanged : ( ev : Event ) => void ; public set oncharacteristicvaluechanged ( fn ) { if ( this . _oncharacteristicvaluechanged ) { this . removeEventListener ( "characteristicvaluechanged" , this . _oncharacteristicvaluechanged ) ; } this . _oncharacteristicvaluechanged = fn ; this . addEventListener ( "characteristicvaluechanged" , this . _oncharacteristicvaluechanged ) ; } param init constructor ( init ) { super ( ) ; this . service = init . service ; this . uuid = init . uuid ; this . properties = init . properties ; this . _value = init . value ; this . handle = this . uuid ; } private setValue ( value ? , emit ? ) { this . _value = value ; if ( emit ) { this . dispatchEvent ( new DOMEvent ( this , "characteristicvaluechanged" ) ) ; this . service . dispatchEvent ( new DOMEvent ( this , "characteristicvaluechanged" ) ) ; this . service . device . dispatchEvent ( new DOMEvent ( this , "characteristicvaluechanged" ) ) ; this . service . device . _bluetooth . dispatchEvent ( new DOMEvent ( this , "characteristicvaluechanged" ) ) ; } } param descriptor returns public getDescriptor ( descriptor ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "getDescriptor error: device not connected" ) ; if ( ! descriptor ) return reject ( "getDescriptor error: no descriptor specified" ) ; this . getDescriptors ( descriptor ) . then ( descriptors => { if ( descriptors . length !== 1 ) return reject ( "getDescriptor error: descriptor not found" ) ; resolve ( descriptors [ 0 ] ) ; } ) . catch ( error => { reject ( `getDescriptor error: ${ error }` ) ; } ) ; } ) ; } param descriptor returns public getDescriptors ( descriptor ? ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "getDescriptors error: device not connected" ) ; function complete ( ) { if ( ! descriptor ) return resolve ( this . descriptors ) ; const filtered = this . descriptors . filter ( descriptorObject => { return ( descriptorObject . uuid === getDescriptorUUID ( descriptor ) ) ; } ) ; if ( filtered . length !== 1 ) return reject ( "getDescriptors error: descriptor not found" ) ; resolve ( filtered ) ; } if ( this . descriptors ) return complete . call ( this ) ; adapter . discoverDescriptors ( this . handle , [ ] , descriptors => { this . descriptors = descriptors . map ( descriptorInfo => { Object . assign ( descriptorInfo , { characteristic : this } ) ; return new BluetoothRemoteGATTDescriptor ( descriptorInfo ) ; } ) ; complete . call ( this ) ; } , error => { reject ( `getDescriptors error: ${ error }` ) ; } ) ; } ) ; } returns public readValue ( ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "readValue error: device not connected" ) ; adapter . readCharacteristic ( this . handle , dataView => { this . setValue ( dataView , true ) ; resolve ( dataView ) ; } , error => { reject ( `readValue error: ${ error }` ) ; } ) ; } ) ; } param value public writeValue ( value ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "writeValue error: device not connected" ) ; function isView ( source ) { return ( source as ArrayBufferView ) . buffer !== undefined ; } const arrayBuffer = isView ( value ) ? value . buffer : value ; const dataView = new DataView ( arrayBuffer ) ; adapter . writeCharacteristic ( this . handle , dataView , ( ) => { this . setValue ( dataView ) ; resolve ( ) ; } , error => { reject ( `writeValue error: ${ error }` ) ; } ) ; } ) ; } param value public writeValueWithResponse ( value ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "writeValue error: device not connected" ) ; function isView ( source ) { return ( source as ArrayBufferView ) . buffer !== undefined ; } const arrayBuffer = isView ( value ) ? value . buffer : value ; const dataView = new DataView ( arrayBuffer ) ; adapter . writeCharacteristic ( this . handle , dataView , ( ) => { this . setValue ( dataView ) ; resolve ( ) ; } , error => { reject ( `writeValue error: ${ error }` ) ; } , false ) ; } ) ; } param value public writeValueWithoutResponse ( value ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "writeValue error: device not connected" ) ; function isView ( source ) { return ( source as ArrayBufferView ) . buffer !== undefined ; } const arrayBuffer = isView ( value ) ? value . buffer : value ; const dataView = new DataView ( arrayBuffer ) ; adapter . writeCharacteristic ( this . handle , dataView , ( ) => { this . setValue ( dataView ) ; resolve ( ) ; } , error => { reject ( `writeValue error: ${ error }` ) ; } , true ) ; } ) ; } returns public startNotifications ( ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "startNotifications error: device not connected" ) ; adapter . enableNotify ( this . handle , dataView => { this . setValue ( dataView , true ) ; } , ( ) => { resolve ( this ) ; } , error => { reject ( `startNotifications error: ${ error }` ) ; } ) ; } ) ; } returns public stopNotifications ( ) { return new Promise ( ( resolve , reject ) => { if ( ! this . service . device . gatt . connected ) return reject ( "stopNotifications error: device not connected" ) ; adapter . disableNotify ( this . handle , ( ) => { resolve ( this ) ; } , error => { reject ( `stopNotifications error: ${ error }` ) ; } ) ; } ) ; } }