import { Characteristic , Peripheral , Service } from "@abandonware/noble" ; import Debug = require ( "debug" ) ; import { EventEmitter } from "events" ; import { IBLEAbstraction } from "./interfaces" ; const debug = Debug ( "bledevice" ) ; export class NobleDevice extends EventEmitter implements IBLEAbstraction { private _noblePeripheral : Peripheral ; private _uuid : string ; private _name : string = "" ; private _listeners : { [ uuid ] : any ; } = { } ; private _characteristics : { [ uuid ] : Characteristic ; } = { } ; private _queue : Promise < any > = Promise . resolve ( ) ; private _mailbox : Buffer [ ] = [ ] ; private _connected : boolean = false ; private _connecting : boolean = false ; constructor ( device ) { super ( ) ; this . _noblePeripheral = device ; this . _uuid = device . uuid ; device . on ( "disconnect" , ( ) => { this . _connecting = false ; this . _connected = false ; this . emit ( "disconnect" ) ; } ) ; setTimeout ( ( ) => { this . _name = device . advertisement . localName ; this . emit ( "discoverComplete" ) ; } , 1000 ) ; } public get uuid ( ) { return this . _uuid ; } public get name ( ) { return this . _name ; } public get connecting ( ) { return this . _connecting ; } public get connected ( ) { return this . _connected ; } public connect ( ) { return new Promise < void > ( ( resolve , reject ) => { this . _connecting = true ; this . _noblePeripheral . connect ( ( err ) => { if ( err ) { return reject ( err ) ; } this . _connecting = false ; this . _connected = true ; return resolve ( ) ; } ) ; } ) ; } public disconnect ( ) { return new Promise < void > ( ( resolve ) => { this . _noblePeripheral . disconnect ( ) ; return resolve ( ) ; } ) ; } public discoverCharacteristicsForService ( uuid ) { return new Promise < void > ( async ( discoverResolve , discoverReject ) => { uuid = this . _sanitizeUUID ( uuid ) ; this . _noblePeripheral . discoverServices ( [ uuid ] , ( err , services ) => { if ( err ) { return discoverReject ( err ) ; } debug ( "Service/characteristic discovery started" ) ; const servicePromises = [ ] ; services . forEach ( ( service ) => { servicePromises . push ( new Promise ( ( resolve ) => { service . discoverCharacteristics ( [ ] , ( err , characteristics ) => { characteristics . forEach ( ( characteristic ) => { this . _characteristics [ characteristic . uuid ] = characteristic ; } ) ; return resolve ( ) ; } ) ; } ) ) ; } ) ; Promise . all ( servicePromises ) . then ( ( ) => { debug ( "Service/characteristic discovery finished" ) ; return discoverResolve ( ) ; } ) ; } ) ; } ) ; } public subscribeToCharacteristic ( uuid , callback ) { uuid = this . _sanitizeUUID ( uuid ) ; this . _characteristics [ uuid ] . on ( "data" , ( data ) => { return callback ( data ) ; } ) ; this . _characteristics [ uuid ] . subscribe ( ( err ) => { if ( err ) { throw new Error ( err ) ; } } ) ; } public addToCharacteristicMailbox ( uuid , data ) { this . _mailbox . push ( data ) ; } public readFromCharacteristic ( uuid , callback ) { uuid = this . _sanitizeUUID ( uuid ) ; this . _characteristics [ uuid ] . read ( ( err , data ) => { return callback ( err , data ) ; } ) ; } public writeToCharacteristic ( uuid , data ) { return new Promise < void > ( ( resolve , reject ) => { uuid = this . _sanitizeUUID ( uuid ) ; this . _characteristics [ uuid ] . write ( data , false , ( error ) => { if ( error ) { return reject ( error ) ; } return resolve ( ) ; } ) ; } ) ; } private _sanitizeUUID ( uuid ) { return uuid . replace ( /-/g , "" ) ; } }