UNPKG

obniz

Version:

obniz sdk for javascript

955 lines 90.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Hci = void 0; /** * @packageDocumentation * @ignore */ const eventemitter3_1 = __importDefault(require("eventemitter3")); const ObnizError_1 = require("../../../../ObnizError"); const bleHelper_1 = __importDefault(require("../bleHelper")); /* eslint rulesdir/non-ascii: 0 */ // eslint-disable-next-line @typescript-eslint/no-namespace var COMMANDS; (function (COMMANDS) { COMMANDS.HCI_COMMAND_PKT = 0x01; COMMANDS.HCI_ACLDATA_PKT = 0x02; COMMANDS.HCI_EVENT_PKT = 0x04; COMMANDS.ACL_START_NO_FLUSH = 0x00; COMMANDS.ACL_CONT = 0x01; COMMANDS.ACL_START = 0x02; COMMANDS.EVT_DISCONN_COMPLETE = 0x05; COMMANDS.EVT_ENCRYPT_CHANGE = 0x08; COMMANDS.EVT_CMD_COMPLETE = 0x0e; COMMANDS.EVT_CMD_STATUS = 0x0f; COMMANDS.EVT_NUMBER_OF_COMPLETED_PACKETS = 0x13; COMMANDS.EVT_ENCRYPTION_KEY_REFRESH_COMPLETE = 0x30; COMMANDS.EVT_LE_META_EVENT = 0x3e; COMMANDS.EVT_LE_CONN_COMPLETE = 0x01; COMMANDS.EVT_LE_ADVERTISING_REPORT = 0x02; COMMANDS.EVT_LE_CONN_UPDATE_COMPLETE = 0x03; COMMANDS.EVT_LE_ENHANCED_CONNECTION_COMPLETE = 0x0a; COMMANDS.EVT_LE_PHY_UPDATE_COMPLETE = 0x0c; // LE PHY アップデート完了イベント COMMANDS.EVT_LE_EXTENDED_ADVERTISING_REPORT = 0x0d; // LE拡張広告レポートイベント COMMANDS.EVT_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED = 0x0e; // LE 定期的広告同期確立イベント COMMANDS.EVT_LE_PERIODIC_ADVERTISING_REPORT_EVENT = 0x0f; // LE定期広告レポートイベント COMMANDS.EVT_LE_PERIODIC_ADVERTISING_SYNC_LOST_EVENT = 0x10; // 周期的広告パケットをタイムアウト時間内に受信しなかった COMMANDS.EVT_LE_SCAN_TIMEOUT_EVENT = 0x11; // LEスキャンタイムアウトイベント COMMANDS.EVT_LE_ADVERTISING_SET_TERMINATED_EVENT = 0x12; // LE 広告セット終了イベント COMMANDS.EVT_LE_SCAN_REQUEST_RECEIVED_EVENT = 0x13; // LE スキャン要求受信イベント COMMANDS.OGF_LINK_CTL = 0x01; COMMANDS.OCF_DISCONNECT = 0x0006; COMMANDS.OGF_LINK_POLICY = 0x02; COMMANDS.OGF_WRITE_DEFAULT_LINK_POLICY_SETTINGS = 0x0f; COMMANDS.OGF_HOST_CTL = 0x03; COMMANDS.OCF_SET_EVENT_MASK = 0x0001; COMMANDS.OCF_RESET = 0x0003; COMMANDS.OCF_READ_LOCAL_NAME = 0x0014; COMMANDS.OCF_WRITE_PAGE_TIMEOUT = 0x0018; COMMANDS.OCF_WRITE_CLASS_OF_DEVICE = 0x0024; COMMANDS.OCF_WRITE_INQUIRY_SCAN_TYPE = 0x0043; COMMANDS.OCF_WRITE_INQUIRY_MODE = 0x0045; COMMANDS.OCF_WRITE_PAGE_SCAN_TYPE = 0x0047; COMMANDS.OCF_WRITE_SIMPLE_PAIRING_MODE = 0x0056; COMMANDS.OCF_SET_EVENT_MASK_PAGE_2 = 0x0063; COMMANDS.OCF_READ_LE_HOST_SUPPORTED = 0x006c; COMMANDS.OCF_WRITE_LE_HOST_SUPPORTED = 0x006d; COMMANDS.OGF_INFO_PARAM = 0x04; COMMANDS.OCF_READ_LOCAL_VERSION = 0x0001; COMMANDS.OCF_READ_LOCAL_SUPPORTED_COMMANDS = 0x0002; COMMANDS.OCF_READ_LOCAL_SUPPORTED_FEATURES = 0x0003; COMMANDS.OCF_READ_LOCAL_EXTENDED_FEATURES = 0x0004; COMMANDS.OCF_READ_BUFFER_SIZE = 0x0005; COMMANDS.OCF_READ_BD_ADDR = 0x0009; COMMANDS.OGF_STATUS_PARAM = 0x05; COMMANDS.OCF_READ_RSSI = 0x0005; COMMANDS.OGF_LE_CTL = 0x08; COMMANDS.OCF_LE_SET_EVENT_MASK = 0x0001; COMMANDS.OCF_LE_READ_BUFFER_SIZE = 0x0002; COMMANDS.OCF_LE_READ_LOCAL_SUPPORTED_FEATURES = 0x0003; COMMANDS.OCF_LE_SET_RANDOM_ADDRESS = 0x0005; COMMANDS.OCF_LE_SET_ADVERTISING_PARAMETERS = 0x0006; COMMANDS.OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER = 0x0007; COMMANDS.OCF_LE_SET_ADVERTISING_DATA = 0x0008; COMMANDS.OCF_LE_SET_SCAN_RESPONSE_DATA = 0x0009; COMMANDS.OCF_LE_SET_ADVERTISE_ENABLE = 0x000a; COMMANDS.OCF_LE_SET_SCAN_PARAMETERS = 0x000b; COMMANDS.OCF_LE_SET_SCAN_ENABLE = 0x000c; COMMANDS.OCF_LE_CREATE_CONN = 0x000d; COMMANDS.OCF_LE_CREATE_CONN_CANCEL = 0x000e; COMMANDS.OCF_LE_READ_WHITE_LIST_SIZE = 0x000f; COMMANDS.OCF_LE_CLEAR_WHITE_LIST = 0x0010; COMMANDS.OCF_LE_CONN_UPDATE = 0x0013; COMMANDS.OCF_LE_ENCRYPT = 0x0017; COMMANDS.OCF_LE_RAND = 0x0018; COMMANDS.OCF_LE_START_ENCRYPTION = 0x0019; COMMANDS.OCF_LE_LTK_NEG_REPLY = 0x001b; COMMANDS.OCF_LE_READ_SUPPORTED_STATES = 0x001c; COMMANDS.OCF_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH = 0x0023; COMMANDS.OCF_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH = 0x0024; COMMANDS.OCF_LE_CLEAR_RESOLVING_LIST = 0x0029; COMMANDS.OCF_LE_READ_RESOLVING_LIST_SIZE = 0x002a; COMMANDS.OCF_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT = 0x002e; COMMANDS.OCF_LE_READ_MAXIMUM_DATA_LENGTH = 0x002f; COMMANDS.OCF_LE_READ_PHY = 0x0030; COMMANDS.OCF_LE_SET_DEFAULT_PHY = 0x0031; COMMANDS.OCF_LE_SET_PHY = 0x0032; COMMANDS.OCF_LE_SET_EXTENDED_ADVERTISING_PARAMETERS = 0x0036; // ExAdv COMMANDS.OCF_LE_SET_EXTENDED_ADVERTISING_DATA = 0x0037; // ExAdv COMMANDS.OCF_LE_SET_EXTENDED_SCAN_RESPONSE_DATA = 0x0038; // ExAdv COMMANDS.OCF_LE_SET_EXTENDED_ADVERTISING_ENABLE = 0x0039; // ExAdv COMMANDS.OCF_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH = 0x003a; COMMANDS.OCF_LE_CLEAR_ADVERTISING_SETS = 0x003d; // ExAdv COMMANDS.OCF_LE_SET_PERIODIC_ADVERTISING_PARAMETERS = 0x003e; COMMANDS.OCF_LE_SET_PERIODIC_ADVERTISING_DATA = 0x003f; COMMANDS.OCF_LE_SET_PERIODIC_ADVERTISING_ENABLE = 0x0040; COMMANDS.OCF_LE_SET_EXTENDED_SCAN_PARAMETERS = 0x0041; // ExAdv COMMANDS.OCF_LE_SET_EXTENDED_SCAN_ENABLE = 0x0042; // ExAdv COMMANDS.OCF_LE_EXTENDED_CREATE_CONNECTION = 0x0043; // ExAdv COMMANDS.OCF_LE_PERIODIC_ADVERTISING_CREATE_SYNC = 0x0044; COMMANDS.OCF_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL = 0x0045; COMMANDS.OCF_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC = 0x0046; COMMANDS.OCF_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST = 0x0047; COMMANDS.OCF_LE_REMOVE_DEVICE_TO_PERIODIC_ADVERTISER_LIST = 0x0048; COMMANDS.OCF_LE_CLEAR_DEVICE_TO_PERIODIC_ADVERTISER_LIST = 0x0049; /* OGF_LINK_CTL : 0x01 */ COMMANDS.DISCONNECT_CMD = COMMANDS.OCF_DISCONNECT | (COMMANDS.OGF_LINK_CTL << 10); /* OGF_LINK_POLICY: 0x02 */ COMMANDS.WRITE_DEFAULT_LINK_POLICY_SETTINGS_CMD = COMMANDS.OGF_WRITE_DEFAULT_LINK_POLICY_SETTINGS | (COMMANDS.OGF_LINK_POLICY << 10); /* OGF_HOST_CTL : 0x03 */ COMMANDS.SET_EVENT_MASK_CMD = COMMANDS.OCF_SET_EVENT_MASK | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.RESET_CMD = COMMANDS.OCF_RESET | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.READ_LOCAL_NAME_CMD = COMMANDS.OCF_READ_LOCAL_NAME | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_PAGE_TIMEOUT_CMD = COMMANDS.OCF_WRITE_PAGE_TIMEOUT | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_CLASS_OF_DEVICE_CMD = COMMANDS.OCF_WRITE_CLASS_OF_DEVICE | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_INQUIRY_SCAN_TYPE_CMD = COMMANDS.OCF_WRITE_INQUIRY_SCAN_TYPE | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_INQUIRY_MODE_CMD = COMMANDS.OCF_WRITE_INQUIRY_MODE | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_PAGE_SCAN_TYPE_CMD = COMMANDS.OCF_WRITE_PAGE_SCAN_TYPE | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_SIMPLE_PAIRING_MODE_CMD = COMMANDS.OCF_WRITE_SIMPLE_PAIRING_MODE | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.SET_EVENT_MASK_PAGE_2_CMD = COMMANDS.OCF_SET_EVENT_MASK_PAGE_2 | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.READ_LE_HOST_SUPPORTED_CMD = COMMANDS.OCF_READ_LE_HOST_SUPPORTED | (COMMANDS.OGF_HOST_CTL << 10); COMMANDS.WRITE_LE_HOST_SUPPORTED_CMD = COMMANDS.OCF_WRITE_LE_HOST_SUPPORTED | (COMMANDS.OGF_HOST_CTL << 10); /* OGF_INFO_PARAM : 0x04 */ COMMANDS.READ_LOCAL_VERSION_CMD = COMMANDS.OCF_READ_LOCAL_VERSION | (COMMANDS.OGF_INFO_PARAM << 10); COMMANDS.READ_LOCAL_SUPPORTED_COMMANDS_CMD = COMMANDS.OCF_READ_LOCAL_SUPPORTED_COMMANDS | (COMMANDS.OGF_INFO_PARAM << 10); COMMANDS.READ_LOCAL_SUPPORTED_FEATURES_CMD = COMMANDS.OCF_READ_LOCAL_SUPPORTED_FEATURES | (COMMANDS.OGF_INFO_PARAM << 10); COMMANDS.READ_LOCAL_EXTENDED_FEATURES_CMD = COMMANDS.OCF_READ_LOCAL_EXTENDED_FEATURES | (COMMANDS.OGF_INFO_PARAM << 10); COMMANDS.READ_BUFFER_SIZE_CMD = COMMANDS.OCF_READ_BUFFER_SIZE | (COMMANDS.OGF_INFO_PARAM << 10); COMMANDS.READ_BD_ADDR_CMD = COMMANDS.OCF_READ_BD_ADDR | (COMMANDS.OGF_INFO_PARAM << 10); /* OGF_STATUS_PARAM: 0x05 */ COMMANDS.READ_RSSI_CMD = COMMANDS.OCF_READ_RSSI | (COMMANDS.OGF_STATUS_PARAM << 10); /* OGF_LE_CTL: 0x08 */ COMMANDS.LE_SET_EVENT_MASK_CMD = COMMANDS.OCF_LE_SET_EVENT_MASK | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_BUFFER_SIZE_CMD = COMMANDS.OCF_LE_READ_BUFFER_SIZE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_LOCAL_SUPPORTED_FEATURES_CMD = COMMANDS.OCF_LE_READ_LOCAL_SUPPORTED_FEATURES | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_RANDOM_ADDRESS_CMD = COMMANDS.OCF_LE_SET_RANDOM_ADDRESS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_ADVERTISING_CHANNEL_TX_POWER_CMD = COMMANDS.OCF_LE_READ_ADVERTISING_CHANNEL_TX_POWER | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_SCAN_PARAMETERS_CMD = COMMANDS.OCF_LE_SET_SCAN_PARAMETERS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_SCAN_ENABLE_CMD = COMMANDS.OCF_LE_SET_SCAN_ENABLE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CREATE_CONN_CMD = COMMANDS.OCF_LE_CREATE_CONN | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CREATE_CONN_CANCEL_CMD = COMMANDS.OCF_LE_CREATE_CONN_CANCEL | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CONN_UPDATE_CMD = COMMANDS.OCF_LE_CONN_UPDATE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_START_ENCRYPTION_CMD = COMMANDS.OCF_LE_START_ENCRYPTION | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_ADVERTISING_PARAMETERS_CMD = COMMANDS.OCF_LE_SET_ADVERTISING_PARAMETERS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_ENCRYPT_CMD = COMMANDS.OCF_LE_ENCRYPT | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_RAND_CMD = COMMANDS.OCF_LE_RAND | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_ADVERTISING_DATA_CMD = COMMANDS.OCF_LE_SET_ADVERTISING_DATA | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_SCAN_RESPONSE_DATA_CMD = COMMANDS.OCF_LE_SET_SCAN_RESPONSE_DATA | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_ADVERTISE_ENABLE_CMD = COMMANDS.OCF_LE_SET_ADVERTISE_ENABLE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_LTK_NEG_REPLY_CMD = COMMANDS.OCF_LE_LTK_NEG_REPLY | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_WHITE_LIST_SIZE_CMD = COMMANDS.OCF_LE_READ_WHITE_LIST_SIZE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CLEAR_WHITE_LIST_CMD = COMMANDS.OCF_LE_CLEAR_WHITE_LIST | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_SUPPORTED_STATES_CMD = COMMANDS.OCF_LE_READ_SUPPORTED_STATES | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_CMD = COMMANDS.OCF_LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_CMD = COMMANDS.OCF_LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CLEAR_RESOLVING_LIST_CMD = COMMANDS.OCF_LE_CLEAR_RESOLVING_LIST | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_RESOLVING_LIST_SIZE_CMD = COMMANDS.OCF_LE_READ_RESOLVING_LIST_SIZE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_CMD = COMMANDS.OCF_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_MAXIMUM_DATA_LENGTH_CMD = COMMANDS.OCF_LE_READ_MAXIMUM_DATA_LENGTH | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_DEFAULT_PHY_CMD = COMMANDS.OCF_LE_SET_DEFAULT_PHY | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_PHY_CMD = COMMANDS.OCF_LE_READ_PHY | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_PHY_CMD = COMMANDS.OCF_LE_SET_PHY | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_EXTENDED_ADVERTISING_PARAMETERS_CMD = COMMANDS.OCF_LE_SET_EXTENDED_ADVERTISING_PARAMETERS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_EXTENDED_ADVERTISING_DATA_CMD = COMMANDS.OCF_LE_SET_EXTENDED_ADVERTISING_DATA | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_EXTENDED_SCAN_RESPONSE_DATA_CMD = COMMANDS.OCF_LE_SET_EXTENDED_SCAN_RESPONSE_DATA | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_EXTENDED_ADVERTISING_ENABLE_CMD = COMMANDS.OCF_LE_SET_EXTENDED_ADVERTISING_ENABLE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_CMD = COMMANDS.OCF_LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CLEAR_ADVERTISING_SETS_CMD = COMMANDS.OCF_LE_CLEAR_ADVERTISING_SETS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_PERIODIC_ADVERTISING_PARAMETERS_CMD = COMMANDS.OCF_LE_SET_PERIODIC_ADVERTISING_PARAMETERS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_PERIODIC_ADVERTISING_DATA_CMD = COMMANDS.OCF_LE_SET_PERIODIC_ADVERTISING_DATA | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_PERIODIC_ADVERTISING_ENABLE_CMD = COMMANDS.OCF_LE_SET_PERIODIC_ADVERTISING_ENABLE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_EXTENDED_SCAN_PARAMETERS_CMD = COMMANDS.OCF_LE_SET_EXTENDED_SCAN_PARAMETERS | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_SET_EXTENDED_SCAN_ENABLE_CMD = COMMANDS.OCF_LE_SET_EXTENDED_SCAN_ENABLE | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_EXTENDED_CREATE_CONNECTION_CMD = COMMANDS.OCF_LE_EXTENDED_CREATE_CONNECTION | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_PERIODIC_ADVERTISING_CREATE_SYNC_CMD = COMMANDS.OCF_LE_PERIODIC_ADVERTISING_CREATE_SYNC | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL_CMD = COMMANDS.OCF_LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_PERIODIC_ADVERTISING_TERMINATE_SYNC_CMD = COMMANDS.OCF_LE_PERIODIC_ADVERTISING_TERMINATE_SYNC | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST_CMD = COMMANDS.OCF_LE_ADD_DEVICE_TO_PERIODIC_ADVERTISER_LIST | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_REMOVE_DEVICE_TO_PERIODIC_ADVERTISER_LIST_CMD = COMMANDS.OCF_LE_REMOVE_DEVICE_TO_PERIODIC_ADVERTISER_LIST | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.LE_CLEAR_DEVICE_TO_PERIODIC_ADVERTISER_LIST_CMD = COMMANDS.OCF_LE_CLEAR_DEVICE_TO_PERIODIC_ADVERTISER_LIST | (COMMANDS.OGF_LE_CTL << 10); COMMANDS.HCI_OE_USER_ENDED_CONNECTION = 0x13; })(COMMANDS || (COMMANDS = {})); const hci_status_json_1 = __importDefault(require("./hci-status.json")); /** * @ignore */ class Hci extends eventemitter3_1.default { constructor(obnizHci) { super(); this._state = 'poweredOff'; this._aclStreamObservers = {}; this._extendedAdvertiseJoinData = {}; /** * @ignore * @private */ this.debugHandler = () => { // do nothing. }; this._obnizHci = obnizHci; this._obnizHci.Obniz.on('_close', () => { this.stateChange('poweredOff'); }); this._socket = { write: (data) => { const arr = Array.from(data); this._obnizHci.write(arr); // console.log( // 'SEND:', // Buffer.from(arr) // .toString('hex') // .match(/.{1,2}/g)! // .join(' ') // ); }, }; this._obnizHci.hciProtocolOnSocketData = this.onSocketData.bind(this); this._obnizHci.onread = this._obnizHci.hciProtocolOnSocketData; this.resetBuffers(); } /** * @ignore * @private */ _reset() { this.stateChange('poweredOff'); this.resetBuffers(); } async initWait() { await this.resetWait(); } setEventMaskCommand(mask) { const cmd = Buffer.alloc(12); const eventMask = Buffer.from(mask, 'hex'); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.SET_EVENT_MASK_CMD, 1); // length cmd.writeUInt8(eventMask.length, 3); eventMask.copy(cmd, 4); this.debug('set event mask - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async resetWait() { if (this._obnizHci.Obniz.hw === 'cc3235mod') { await this.resetForNrf52832Wait(); } else { await this.resetForOldObnizjsWait(); // await this.resetForEsp32Wait(); } } async resetForNrf52832Wait() { this._reset(); await this.resetCommandWait(); const features = await this.readLocalSupportedFeaturesCommandWait(); const localVersion = await this.readLocalVersionCommandWait(); const addr = await this.readBdAddrWait(); const bufSize = await this.leReadBufferSizeWait(); const leFeatures = await this.leReadLocalSupportedFeaturesCommandWait(); const leSupportedStates = await this.leReadSupportedStatesCommandWait(); const supportedCommands = await this.readLocalSupportedCommandWait(); // this.setEventMaskCommand('fffffbff07f8bf3d'); // this.setLeEventMaskCommand('1f00000000000000'); this.setEventMaskCommand('90E8040200800020'); this.setLeEventMaskCommand('5F0E080000000000'); const txPower = await this.leReadAdvertisingPhysicalChannelTxPowerCommandWait(); const whiteListSize = await this.leReadWhiteListSizeWait(); await this.leClearWhiteListCommandWait(); const resolvingListSize = await this.leReadResolvingListSizeCommandWait(); await this.leClearResolvingListCommandWait(); await this.leSetResolvablePrivateAddressTimeoutCommandWait(0x0384); const maximumDataLength = await this.leReadMaximumDataLengthCommandWait(); this.setEventMaskPage2('0000800000000000'); // TODO const defaultDataLength = await this.leReadSuggestedDefaultDataLengthCommandWait(); // await this.leWriteSuggestedDefaultDataLengthCommandWait(0x00fb, 0x0a90); await this.leSetDefaultPhyCommandWait(0, 0, 1); // await this.setAdvertisingDataWait(Buffer.alloc(31)); await this.setRandomDeviceAddressWait(); } async resetForOldObnizjsWait() { this._reset(); await this.resetCommandWait(); this.setEventMaskCommand('fffffbff07f8bf3d'); // this.setLeEventMaskCommand('1ff8070000000000'); this.setLeEventMaskCommand('1f1A000000000000'); const { hciVer, hciRev, lmpVer, manufacturer, lmpSubVer, } = await this.readLocalVersionCommandWait(); this.writeLeHostSupportedCommand(); await this.readLeHostSupportedWait(); const addr = await this.readBdAddrWait(); const bufsize = await this.leReadBufferSizeWait(); if (bufsize) { this.debug(`Buffer Mtu=${bufsize.aclMtu} aclMaxInProgress=${bufsize.aclMaxInProgress}`); } // await this.setRandomDeviceAddressWait(); if (this._state !== 'poweredOn' && !this._obnizHci._extended) { await this.setScanEnabledWait(false, true); await this.setScanParametersWait(false); this.stateChange('poweredOn'); } } async resetForEsp32Wait() { this._reset(); await this.resetCommandWait(); const bufSize = await this.readBufferSizeWait(); const localVersion = await this.readLocalVersionCommandWait(); const addr = await this.readBdAddrWait(); const localSupportedCommands = await this.readLocalSupportedCommandWait(); const localExtendedFeatures = [ await this.readLocalExtendedFeaturesCommandWait(0), ]; if (localExtendedFeatures[0].maximumPageNumber > 0) { for (let i = 1; i <= localExtendedFeatures[0].maximumPageNumber; i++) { localExtendedFeatures.push(await this.readLocalExtendedFeaturesCommandWait(i)); } } await this.writeSimplePairingModeCommandWait('enabled'); this.writeLeHostSupportedCommand(); const whiteListSize = await this.leReadWhiteListSizeWait(); const leBufSize = await this.leReadBufferSizeWait(); if (leBufSize) { this.debug(`Buffer Mtu=${leBufSize.aclMtu} aclMaxInProgress=${leBufSize.aclMaxInProgress}`); } const supportedStates = await this.leReadSupportedStatesCommandWait(); const localSupportedFeatures = await this.leReadLocalSupportedFeaturesCommandWait(); const resolvingListSize = await this.leReadResolvingListSizeCommandWait(); await this.leWriteSuggestedDefaultDataLengthCommandWait(0x00fb, 0x0848); const defaultDataLength = await this.leReadSuggestedDefaultDataLengthCommandWait(); this.setLeEventMaskCommand('7f06000000000000'); this.setEventMaskCommand('FFFFFFFFFFFFBF3D'); // this.setLeEventMaskCommand('1f00000000000000'); // this.setEventMaskCommand('fffffbff07f8bf3d'); await this.leClearResolvingListCommandWait(); await this.leSetResolvablePrivateAddressTimeoutCommandWait(0x0384); await this.writeInquiryModeCommandWait('inquiryResultWithRSSIFormatOrExtendedInquiryResultFormat'); await this.writePageScanTypeCommandWait('interlacedScan'); await this.writeInquiryScanTypeCommandWait('interlacedScan'); await this.writeClassOfDeviceCommandWait(0x2c0414); await this.writePageTimeoutCommandWait(0x2000); await this.writeDefaultLinkPolicyCommandWait(['enableSniffMode']); const localName = await this.readLocalNameCommandWait(); this.debug('le localName ' + localName); if (this._state !== 'poweredOn') { await this.setScanEnabledWait(false, true); await this.setScanParametersWait(false); this.stateChange('poweredOn'); } } async resetCommandWait() { const resetResult = await this.writeNoParamCommandWait(COMMANDS.RESET_CMD, 'reset'); return resetResult; } async setRandomDeviceAddressWait() { // await this.leRandWait(); // await this.leEncryptWait(); await this.leSetRandomAddressWait(Buffer.from([254, 117, 174, 251, 138, 21])); } async leEncryptWait(key, plainTextData) { const cmd = Buffer.alloc(4 + 16 + 16); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_ENCRYPT_CMD, 1); // length cmd.writeUInt8(0x0, 3); key.copy(cmd, 4); plainTextData.copy(cmd, 4 + 16); const p = this.readCmdCompleteEventWait(COMMANDS.LE_ENCRYPT_CMD); this.debug('le encrypt - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; const encryptedData = data.result; return { encryptedData }; } async leRandWait() { const cmd = Buffer.alloc(4); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_RAND_CMD, 1); // length cmd.writeUInt8(0x0, 3); const p = this.readCmdCompleteEventWait(COMMANDS.LE_RAND_CMD); this.debug('le rand - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; const randomNumber = data.result; return { randomNumber }; } async leSetRandomAddressWait(randomAddress) { const cmd = Buffer.alloc(4 + 6); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_RANDOM_ADDRESS_CMD, 1); // length cmd.writeUInt8(0x0, 3); randomAddress.copy(cmd, 4); const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_RANDOM_ADDRESS_CMD); this.debug('le set random address - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; } async writeDefaultLinkPolicyCommandWait(mode) { const cmd = Buffer.alloc(6); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.WRITE_DEFAULT_LINK_POLICY_SETTINGS_CMD, 1); // length cmd.writeUInt8(0x02, 3); let modeValue = 0; if (mode.includes('enableRoleSwitch')) { modeValue = modeValue | 0x01; } if (mode.includes('enableHoldMode')) { modeValue = modeValue | 0x02; } if (mode.includes('enableSniffMode')) { modeValue = modeValue | 0x04; } cmd.writeUInt16LE(modeValue, 4); this.debug('write default link policy - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } resetBuffers() { this._handleAclsInProgress = {}; this._handleBuffers = {}; this._aclOutQueue = []; } async readLocalVersionCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.READ_LOCAL_VERSION_CMD, 'read local version'); const hciVer = data.result.readUInt8(0); const hciRev = data.result.readUInt16LE(1); const lmpVer = data.result.readInt8(3); const manufacturer = data.result.readUInt16LE(4); const lmpSubVer = data.result.readUInt16LE(6); if (hciVer < 0x06) { throw new ObnizError_1.ObnizBleUnsupportedHciError(0x06, hciVer); } this.debug(`localVersion ${hciVer} ${hciRev} ${lmpVer} ${manufacturer} ${lmpSubVer}`); return { hciVer, hciRev, lmpVer, manufacturer, lmpSubVer }; } async readLocalNameCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.READ_LOCAL_NAME_CMD, 'read local name'); return data.result.toString('ascii'); } async writePageTimeoutCommandWait(pageTimeout = 0x2000) { const cmd = Buffer.alloc(6); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.WRITE_PAGE_TIMEOUT_CMD, 1); // length cmd.writeUInt8(0x02, 3); cmd.writeUInt16LE(pageTimeout, 4); this.debug('write page timeout - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async writeClassOfDeviceCommandWait(classOfDevice) { const cmd = Buffer.alloc(7); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.WRITE_CLASS_OF_DEVICE_CMD, 1); // length cmd.writeUInt8(0x03, 3); cmd.writeUInt8((classOfDevice >> 0) & 0xff, 4); cmd.writeUInt8((classOfDevice >> 8) & 0xff, 5); cmd.writeUInt8((classOfDevice >> 16) & 0xff, 6); this.debug('write class of device - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async writeInquiryScanTypeCommandWait(scanType) { const data = await this.writeSingleParamCommandWait(COMMANDS.WRITE_INQUIRY_SCAN_TYPE_CMD, scanType, { standardScan: 0x00, interlacedScan: 0x01, }, 'write inquiry mode type '); } async writeInquiryModeCommandWait(inquiryMode) { const data = await this.writeSingleParamCommandWait(COMMANDS.WRITE_INQUIRY_MODE_CMD, inquiryMode, { standardInquiryResultEventFormat: 0x00, inquiryResultFormatWithRSSI: 0x01, inquiryResultWithRSSIFormatOrExtendedInquiryResultFormat: 0x02, }, 'write inquiry mode type '); } async writePageScanTypeCommandWait(pageScanType) { const data = await this.writeSingleParamCommandWait(COMMANDS.WRITE_PAGE_SCAN_TYPE_CMD, pageScanType, { standardScan: 0x00, interlacedScan: 0x01, }, 'write page scan type'); } async writeSimplePairingModeCommandWait(simplePairingMode) { const data = await this.writeSingleParamCommandWait(COMMANDS.WRITE_SIMPLE_PAIRING_MODE_CMD, simplePairingMode, { disabled: 0x00, enabled: 0x01, }, 'write simple pairing mode'); } setEventMaskPage2(mask) { const cmd = Buffer.alloc(12); const leEventMask = Buffer.from(mask, 'hex'); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.SET_EVENT_MASK_PAGE_2_CMD, 1); // length cmd.writeUInt8(leEventMask.length, 3); leEventMask.copy(cmd, 4); this.debug('set le event mask page 2 - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async readLocalSupportedCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.READ_LOCAL_SUPPORTED_COMMANDS_CMD, 'read local supported commands'); this.debug('supportedCommands = ' + data.result.toString('hex')); return data.result; } async readLocalSupportedFeaturesCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.READ_LOCAL_SUPPORTED_FEATURES_CMD, 'read local supported features'); this.debug('supportedFeatures = ' + data.result.toString('hex')); return data.result; } async readLocalExtendedFeaturesCommandWait(page) { const cmd = Buffer.alloc(5); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.READ_LOCAL_EXTENDED_FEATURES_CMD, 1); // length cmd.writeUInt8(1, 3); cmd.writeUInt8(page, 4); const p = this.readCmdCompleteEventWait(COMMANDS.READ_LOCAL_EXTENDED_FEATURES_CMD); this.debug(`read local extended features - writing: ${cmd.toString('hex')}`); this._socket.write(cmd); const resetResult = await p; return { pageNumber: resetResult.result.readUInt8(0), maximumPageNumber: resetResult.result.readUInt8(1), extendedLmpFeatures: resetResult.result.slice(2), }; } async leClearWhiteListCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_CLEAR_WHITE_LIST_CMD, 'le clear white list'); return data.result; } async leReadSupportedStatesCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_SUPPORTED_STATES_CMD, 'le read supported states'); return data.result; } async leReadSuggestedDefaultDataLengthCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH_CMD, 'le read suggested default data length'); return { suggestedMaxTxOctets: data.result.readUInt16LE(0), suggestedMaxTxTime: data.result.readUInt16LE(2), }; } async leWriteSuggestedDefaultDataLengthCommandWait(suggestedMaxTxOctets, suggestedMaxTxTime) { const cmd = Buffer.alloc(8); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH_CMD, 1); // length cmd.writeUInt8(4, 3); cmd.writeUInt16LE(suggestedMaxTxOctets, 4); cmd.writeUInt16LE(suggestedMaxTxTime, 6); this.debug('le write suggested default data length - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async leClearResolvingListCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_CLEAR_RESOLVING_LIST_CMD, 'le clear resolving list'); } async leReadResolvingListSizeCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_RESOLVING_LIST_SIZE_CMD, 'le read resolving list size'); return data.result.readInt8(0); } async leSetResolvablePrivateAddressTimeoutCommandWait(rpaTimeout) { const cmd = Buffer.alloc(6); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_CMD, 1); // length cmd.writeUInt8(2, 3); cmd.writeUInt16LE(rpaTimeout, 4); this.debug('le set resolvable private address timeout - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async leReadMaximumDataLengthCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_MAXIMUM_DATA_LENGTH_CMD, 'le read maximum data length'); return { supportedMaxTxOctets: data.result.readUInt16LE(0), supportedMaxTxTime: data.result.readUInt16LE(2), supportedMaxRxOctets: data.result.readUInt16LE(4), supportedMaxRxTime: data.result.readUInt16LE(6), }; } async leReadLocalSupportedFeaturesCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_LOCAL_SUPPORTED_FEATURES_CMD, 'le read local supported features'); this.debug('read local supported features = ' + data.result.toString('hex')); return data.result; } async leReadPhyCommandWait(connectionHandle) { const cmd = Buffer.alloc(6); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_READ_PHY_CMD, 1); // length cmd.writeUInt8(2, 3); cmd.writeUInt16LE(connectionHandle, 4); const p = this.readCmdCompleteEventWait(COMMANDS.LE_READ_PHY_CMD); this.debug(`read Phy - writing: ${cmd.toString('hex')}`); this._socket.write(cmd); const data = await p; return { status: data.status, connectionHandle: data.result.readUInt16LE(0), txPhy: data.result.readUInt8(2), rxPhy: data.result.readUInt8(3), }; } // 接続後にのみ使用可能 async leSetPhyCommandWait(connectionHandle, allPhys, txPhys, rxPhys, options) { const cmd = Buffer.alloc(11); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_PHY_CMD, 1); // length cmd.writeUInt8(7, 3); cmd.writeUInt16LE(connectionHandle, 4); cmd.writeUInt8(allPhys, 6); cmd.writeUInt8(txPhys, 7); cmd.writeUInt8(rxPhys, 8); cmd.writeUInt16LE(options, 9); this.debug('le set phy - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async setExtendedAdvertisingParametersWait(handle, eventProperties, primaryAdvertisingPhy, secondaryAdvertisingPhy, txPower) { const cmd = Buffer.alloc(29); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EXTENDED_ADVERTISING_PARAMETERS_CMD, 1); // length cmd.writeUInt8(25, 3); const advertisementInterval = Math.floor((process.env.BLENO_ADVERTISING_INTERVAL ? parseFloat(process.env.BLENO_ADVERTISING_INTERVAL) : 100) * 1.6); // data cmd.writeUInt8(handle, 4); cmd.writeUInt16LE(eventProperties, 5); // Advertising_Event_Properties // Broadcast(0x0000)(ADV Data 1650B send) or Scannable(0x0002)(ScanRsp Data 1650B send) cmd.writeUInt16LE(advertisementInterval, 7); // min interval //default 100ms cmd.writeUInt8((advertisementInterval >> 16) & 0xff, 9); // min interval cmd.writeUInt16LE(advertisementInterval * 2, 10); // max interval cmd.writeUInt8(((advertisementInterval * 2) >> 16) & 0xff, 12); // max interval cmd.writeUInt8(0x07, 13); // Primary_Advertising_Channel_Map used 37,38,39ch cmd.writeUInt8(0x00, 14); // Own_Address_Type direct addr type cmd.writeUInt8(0x00, 15); // Peer_Address_Type Buffer.from('000000000000', 'hex').copy(cmd, 16); // direct addr cmd.writeUInt8(0x00, 22); // Advertising_Filter_Policy All Devices cmd.writeUInt8(txPower, 23); // Advertising_Tx_Power cmd.writeUInt8(primaryAdvertisingPhy, 24); // PrimaryAdvertisingPhy cmd.writeUInt8(0x00, 25); // Secondary_Advertising_Max_Skip cmd.writeUInt8(secondaryAdvertisingPhy, 26); // SecondaryAdvertisingPhy cmd.writeUInt8(0x00, 27); // Advertising_SID cmd.writeUInt8(0x00, 28); // Scan_Request_Notification_Enable const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_EXTENDED_ADVERTISING_PARAMETERS_CMD); this.debug('set extended advertisement parameters - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; // this.emit("stateChange", "poweredOn"); // TODO : really need? return { status: data.status, txPower: data.result.readUInt8(0), }; } extendedAdvertiseOperation(index, length) { if (index === 0) { if (length <= 251) return 3; // Operation コンプリートスキャン応答データ return 1; // Operation 断片化されたスキャンレスポンスデータの最初の断片 } if (length - index * 251 <= 251) return 2; // Operation 断片化したスキャンレスポンスデータの最後の断片 return 0; // Operation 断片化したスキャンレスポンスデータの中間断片 } async setExtendedAdvertisingDataWait(handle, data) { for (let i = 0; i < data.length / 251; i++) { const size = data.length - i * 251 > 251 ? 251 : data.length - i * 251; const cmd = Buffer.alloc(size + 4 + 4); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EXTENDED_ADVERTISING_DATA_CMD, 1); // length cmd.writeUInt8(size + 4, 3); // data cmd.writeUInt8(handle, 4); cmd.writeUInt8(this.extendedAdvertiseOperation(i, data.length), 5); cmd.writeUInt8(0x00, 6); // Fragment_Preference cmd.writeUInt8(size, 7); // Data_Length data.copy(cmd, 8, i * 251, i * 251 + size); const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_EXTENDED_ADVERTISING_DATA_CMD); this.debug('set extended advertisement data - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const result = await p; if (result.status !== 0) { return result.status; } } return 0; } // 今の仕様だとScanResponseはExtendedでサポートしていない async setExtendedAdvertisingScanResponseDataWait(handle, data) { for (let i = 0; i < data.length / 251; i++) { const size = data.length - i * 251 > 251 ? 251 : data.length - i * 251; const cmd = Buffer.alloc(size + 4 + 4); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EXTENDED_SCAN_RESPONSE_DATA_CMD, 1); // length cmd.writeUInt8(size + 4, 3); // data cmd.writeUInt8(handle, 4); cmd.writeUInt8(this.extendedAdvertiseOperation(i, data.length), 5); cmd.writeUInt8(0x00, 6); // Fragment_Preference cmd.writeUInt8(size, 7); // Data_Length data.copy(cmd, 8, i * 251, i * 251 + size); const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_EXTENDED_SCAN_RESPONSE_DATA_CMD); this.debug('set extended scan response data - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const result = await p; if (result.status !== 0) { return result.status; } } return 0; } async setExtendedAdvertisingEnableWait(enabled, enableList) { const cmd = Buffer.alloc(enableList.length * 4 + 4 + 2); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EXTENDED_ADVERTISING_ENABLE_CMD, 1); // length cmd.writeUInt8(enableList.length * 4 + 2, 3); // data cmd.writeUInt8(enabled ? 0x01 : 0x00, 4); // enable: 0 -> disabled, 1 -> enabled cmd.writeUInt8(enableList.length, 5); // length for (let i = 0; i < enableList.length; i++) { cmd.writeUInt8(enableList[i].handle, 6 + i * 4); // handle cmd.writeUInt16LE(enableList[i].duration, 7 + i * 4); // duration cmd.writeUInt8(enableList[i].events, 9 + i * 4); // events } const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_EXTENDED_ADVERTISING_ENABLE_CMD); this.debug('set extended advertise enable - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; return data.status; } async leReadMaximumAdvertisingDataLengthWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH_CMD, 'le read maximum advertising data length'); return data.result.readUInt16LE(0); } // 先にsetExtendedAdvertiseEnableWaitで無効化してから行うこと async leClearAdvertisingSetWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_CLEAR_ADVERTISING_SETS_CMD, 'le clear advertising Set'); return data.result.readUInt16LE(0); } async setExtendedScanParametersWait(isActiveScan, usePhy1m = true, usePhyCoded = true) { const booleanToNumber = (flg) => (flg ? 1 : 0); const cmd = Buffer.alloc(7 + (booleanToNumber(usePhy1m) + booleanToNumber(usePhyCoded)) * 5); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EXTENDED_SCAN_PARAMETERS_CMD, 1); // length cmd.writeUInt8(3 + (booleanToNumber(usePhy1m) + booleanToNumber(usePhyCoded)) * 5, 3); // data cmd.writeUInt8(0x00, 4); // Own_Address_Type 公開端末アドレス cmd.writeUInt8(0x00, 5); // Scanning_Filter_Policy:本装置宛でない有向広告パケットを除くすべての広告パケットを受信する cmd.writeUInt8(booleanToNumber(usePhy1m) + (booleanToNumber(usePhyCoded) << 2), 6); // Scanning_PHYs:1M Phy and Coded Phy 0b00000101 for (let i = 0; i < booleanToNumber(usePhy1m) + booleanToNumber(usePhyCoded); i++) { cmd.writeUInt8(isActiveScan ? 0x01 : 0x00, 7 + i * 5); // Scan_Type ActiveScan 1 // コントローラが最後のスキャンを開始してから、プライマリ広告チャネルで次のスキャンを開始するまでの時間間隔。 cmd.writeUInt16LE(0x0010, 8 + i * 5); // Scan_Interval //default 10ms //もともとのスキャン機能のインターバルから引用 // 主広告チャンネルでのスキャンの持続時間 cmd.writeUInt16LE(0x0010, 10 + i * 5); // Scan_Window //default 10ms } const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_EXTENDED_SCAN_PARAMETERS_CMD); this.debug('set extended scan parameters - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; return data.status; } async setExtendedScanEnabledWait(enabled, filterDuplicates) { this._extendedAdvertiseJoinData = {}; const cmd = Buffer.alloc(10); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EXTENDED_SCAN_ENABLE_CMD, 1); // length cmd.writeUInt8(0x06, 3); // data cmd.writeUInt8(enabled ? 0x01 : 0x00, 4); // enable: 0 -> disabled, 1 -> enabled cmd.writeUInt8(filterDuplicates ? 0x01 : 0x00, 5); // 0x01 => filter enabled, 0x00 => filter disable cmd.writeUInt16LE(0x0000, 6); // Scan_Duration 明示的に無効化されるまで連続スキャン 既存のスキャンと同じように cmd.writeUInt16LE(0x0000, 8); // Scan_Period 定期的なスキャンを無効にする 連続スキャンなのではいらない this.debug(`set extended scan ${enabled ? 'enabled' : 'disable'} - writing: ${cmd.toString('hex')}`); const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_EXTENDED_SCAN_ENABLE_CMD); this._socket.write(cmd); const data = await p; return data.status; } async createLeExtendedConnWait(address, addressType, timeout = 90 * 1000, onConnectCallback, pyh1m = true, pyh2m = true, pyhCoded = true) { const booleanToNumber = (flg) => (flg ? 1 : 0); const configCount = booleanToNumber(pyh1m) + booleanToNumber(pyh2m) + booleanToNumber(pyhCoded); const cmd = Buffer.alloc(configCount * 16 + 10 + 4); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_EXTENDED_CREATE_CONNECTION_CMD, 1); // length cmd.writeUInt8(configCount * 16 + 10, 3); const parameter = { interval: 0x0010, window: 0x0010, minInterval: 0x0009, maxInterval: 0x0018, latency: 0x0001, supervisionTimeout: 0x0190, minCeLength: 0x0000, maxCeLength: 0x0000, }; // data cmd.writeUInt8(0x00, 4); // Initiating_Filter_Policy ホワイトリストは使用しません cmd.writeUInt8(0x00, 5); // Own_Address_Type 公開端末アドレス cmd.writeUInt8(addressType === 'random' ? 0x01 : 0x00, 6); // peer address type bleHelper_1.default.hex2reversedBuffer(address, ':').copy(cmd, 7); // peer address cmd.writeUInt8(booleanToNumber(pyh1m) + booleanToNumber(pyh2m) * 2 + booleanToNumber(pyhCoded) * 4, 13); // Initiating_PHY for (let i = 0; i < configCount; i++) { cmd.writeUInt16LE(parameter.interval, 14 + i * 16); // interval cmd.writeUInt16LE(parameter.window, 16 + i * 16); // window cmd.writeUInt16LE(parameter.minInterval, 18 + i * 16); // minInterval cmd.writeUInt16LE(parameter.maxInterval, 20 + i * 16); // maxInterval cmd.writeUInt16LE(parameter.latency, 22 + i * 16); // latency cmd.writeUInt16LE(parameter.supervisionTimeout, 24 + i * 16); // supervisionTimeout cmd.writeUInt16LE(parameter.minCeLength, 26 + i * 16); // minCeLength cmd.writeUInt16LE(parameter.maxCeLength, 28 + i * 16); // maxCeLength } this.debug('create le extended conn - writing: ' + cmd.toString('hex')); const processConnectionCompletePromise = (async () => { const { status, data } = await this.readLeMetaEventWait(COMMANDS.EVT_LE_CONN_COMPLETE, { timeout, waitingFor: 'EVT_LE_CONN_COMPLETE', }); return { status, data: this.parseConnectionCompleteEventData(data) }; })(); const processLeConnectionCompletePromise = (async () => { const { status, data } = await this.readLeMetaEventWait(COMMANDS.EVT_LE_ENHANCED_CONNECTION_COMPLETE, { timeout, waitingFor: 'EVT_LE_ENHANCED_CONNECTION_COMPLETE', }); return { status, data: this.parseLeConnectionCompleteEventData(data) }; })(); this._socket.write(cmd); const result = await Promise.race([ processConnectionCompletePromise, processLeConnectionCompletePromise, ]); return this.processLeConnComplete(result.status, result.data, onConnectCallback); } async leSetDefaultPhyCommandWait(allPhys, txPhys, rxPhys) { const cmd = Buffer.alloc(7); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_DEFAULT_PHY_CMD, 1); // length cmd.writeUInt8(3, 3); cmd.writeUInt8(allPhys, 4); cmd.writeUInt8(txPhys, 5); cmd.writeUInt8(rxPhys, 6); const p = this.readCmdCompleteEventWait(COMMANDS.LE_SET_DEFAULT_PHY_CMD); this.debug('le set default phy - writing: ' + cmd.toString('hex')); this._socket.write(cmd); const data = await p; return data.status; } async leReadAdvertisingPhysicalChannelTxPowerCommandWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_ADVERTISING_CHANNEL_TX_POWER_CMD, 'le read advertising channel tx power'); return data.result.readInt8(0); } async leReadWhiteListSizeWait() { const data = await this.writeNoParamCommandWait(COMMANDS.LE_READ_WHITE_LIST_SIZE_CMD, 'le read white list size'); return data.result.readUInt8(0); } async readBdAddrWait() { const data = await this.writeNoParamCommandWait(COMMANDS.READ_BD_ADDR_CMD, 'read bd addr'); this.addressType = 'public'; this.address = bleHelper_1.default.buffer2reversedHex(data.result, ':'); this.debug('address = ' + this.address); return this.address; } setLeEventMaskCommand(mask) { const cmd = Buffer.alloc(12); const leEventMask = Buffer.from(mask, 'hex'); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_EVENT_MASK_CMD, 1); // length cmd.writeUInt8(leEventMask.length, 3); leEventMask.copy(cmd, 4); this.debug('set le event mask - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async readLeHostSupportedWait() { const data = await this.writeNoParamCommandWait(COMMANDS.READ_LE_HOST_SUPPORTED_CMD, 'read LE host supported'); if (data.status === 0) { const le = data.result.readUInt8(0); const simul = data.result.readUInt8(1); this.debug('\t\t\tle = ' + le); this.debug('\t\t\tsimul = ' + simul); } return data; } writeLeHostSupportedCommand() { const cmd = Buffer.alloc(6); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.WRITE_LE_HOST_SUPPORTED_CMD, 1); // length cmd.writeUInt8(0x02, 3); // data cmd.writeUInt8(0x01, 4); // le cmd.writeUInt8(0x00, 5); // simul this.debug('write LE host supported - writing: ' + cmd.toString('hex')); this._socket.write(cmd); } async setScanParametersWait(isActiveScan) { const cmd = Buffer.alloc(11); // header cmd.writeUInt8(COMMANDS.HCI_COMMAND_PKT, 0); cmd.writeUInt16LE(COMMANDS.LE_SET_SCAN_PARAMETERS_CMD, 1); // length cmd.writeUInt8(0x07, 3); // data cmd.writeUInt8(isActiveScan ? 0x01 : 0x00, 4); // type: 0 -> passive, 1 -> active cmd.writeUInt16LE(0x0010, 5); // internal, ms * 1.6 cmd.writeUInt16LE(0x0010, 7); // window, ms * 1.6 const addressType = this._obnizHci.Obniz.hw === 'cc3235mod' ? 0x01 : 0x00; cmd.writeUInt8(addressType, 9); // own address type: 0 -> public, 1 -> random cmd.writeUInt8(0x00, 10); // filter: 0 -> all event types const p = this.readCmdCompleteEvent