UNPKG

nubli

Version:
158 lines (157 loc) 6.23 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const noble_1 = __importDefault(require("noble")); const smartLockPeripheralFilter_1 = require("./smartLockPeripheralFilter"); const smartLock_1 = require("./smartLock"); const events_1 = __importDefault(require("events")); class Nubli extends events_1.default.EventEmitter { constructor(peripheralFilter = new smartLockPeripheralFilter_1.SmartLockPeripheralFilter(), configPath) { super(); this.noble = noble_1.default; this.debugEnabled = false; this._smartlocks = []; this._configPath = "./config/"; this._scanning = false; this.activeScanning = false; this.peripheralFilter = peripheralFilter; if (configPath) { this._configPath = configPath; } // Override HCI so we can scan passively. this.noble._bindings._hci.setScanParameters = () => { var cmd = new Buffer(11); let HCI_COMMAND_PKT = 0x01; let OCF_LE_SET_SCAN_PARAMETERS = 0x000b; let OGF_LE_CTL = 0x08; let LE_SET_SCAN_PARAMETERS_CMD = OCF_LE_SET_SCAN_PARAMETERS | OGF_LE_CTL << 10; // header cmd.writeUInt8(HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(LE_SET_SCAN_PARAMETERS_CMD, 1); // length cmd.writeUInt8(0x07, 3); if (this.activeScanning) { cmd.writeUInt8(0x01, 4); // type: 0 -> passive, 1 -> active } else { cmd.writeUInt8(0x00, 4); // type: 0 -> passive, 1 -> active } cmd.writeUInt16LE(0x0010, 5); // internal, ms * 1.6 cmd.writeUInt16LE(0x0010, 7); // window, ms * 1.6 cmd.writeUInt8(0x00, 9); // own address type: 0 -> public, 1 -> random cmd.writeUInt8(0x00, 10); // filter: 0 -> all event types this.noble._bindings._hci._socket.write(cmd); }; this.noble.on('discover', (peripheral) => this.peripheralDiscovered(peripheral)); this.noble.on('stateChange', (state) => this.stateChange(state)); this.noble.on('scanStart', () => { if (!this._scanning) { this.emit("startedScanning"); this.debug("Started scanning"); } this._scanning = true; }); // When we connect to an peripheral, scanning will be stopped. // This way we make sure to start scanning again after a short delay (500ms). this.noble.on('scanStop', () => { if (this._scanning) { setTimeout(() => { if (this._scanning) { this.startScanning(); } }, 500); } else { this.emit("stoppedScanning"); this.debug("Stopped scanning"); } }); } setDebug(debugEnabled) { this.debugEnabled = debugEnabled; } peripheralDiscovered(peripheral) { for (let smartLock of this._smartlocks) { if (peripheral.uuid == smartLock.uuid) { if ("manufacturerData" in peripheral.advertisement && peripheral.advertisement.manufacturerData !== null && peripheral.advertisement.manufacturerData !== undefined) { smartLock.updateManufacturerData(peripheral.advertisement.manufacturerData); } return; } } if (!this.peripheralFilter.handle(peripheral)) return; this.debug("Peripheral matched filter: " + peripheral.id + " - " + peripheral.advertisement.localName); let smartLock = new smartLock_1.SmartLock(this, peripheral); this._smartlocks.push(smartLock); this.emit("smartLockDiscovered", smartLock); } get smartlocks() { return this._smartlocks; } stateChange(state) { this.debug("state change: " + state); this.emit("state", state); if (state == "poweredOn") { this.emit("readyToScan"); } } debug(message) { if (this.debugEnabled) { console.log(new Date().toLocaleString(), message); } } readyToScan() { return this.noble.state == "poweredOn"; } onReadyToScan(timeout = 10) { return __awaiter(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { if (this.readyToScan()) { resolve(); } else { this.once('readyToScan', () => { resolve(); }); } setTimeout(() => { reject('Adapter still not ready after ' + timeout + " seconds"); }, timeout * 1000); }); }); } startActiveScanning() { this.activeScanning = true; this.startScanning(); } startScanning() { if (!this.readyToScan()) { throw new Error("Scanning only possible if the adapter is ready."); } this.noble.startScanning([], true); } stopScanning() { this._scanning = false; this.activeScanning = false; this.noble.stopScanning(); } get configPath() { return this._configPath; } get scanning() { return this._scanning; } } exports.Nubli = Nubli;