UNPKG

@robotical/roboticaljs

Version:

Javascript/TS library for Robotical products

201 lines 8.73 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const raftjs_1 = require("@robotical/raftjs"); const SettingsManager_1 = tslib_1.__importDefault(require("./SettingsManager")); const main_1 = require("./main"); const SystemTypeGeneric_1 = tslib_1.__importDefault(require("./SystemTypeGeneric/SystemTypeGeneric")); const sysTypeManager = raftjs_1.RaftSysTypeManager.getInstance(); const settingsManager = SettingsManager_1.default.getInstance(); try { sysTypeManager.addSystemType('Cog', () => new main_1.SystemTypeCog()); } catch (e) { raftjs_1.RaftLog.warn(`ConnManager - failed to add system type Cog: ${e}`); } try { sysTypeManager.addSystemType('RIC', () => new main_1.SystemTypeMarty()); } catch (e) { raftjs_1.RaftLog.warn(`ConnManager - failed to add system type RIC: ${e}`); } try { sysTypeManager.addDefaultSystemType(() => new SystemTypeGeneric_1.default()); } catch (e) { raftjs_1.RaftLog.warn(`ConnManager - failed to add default system type: ${e}`); } const connectedDevices = []; class ConnManager { constructor() { // Connector this._connector = new raftjs_1.RaftConnector(async (systemUtils) => { const systemInfo = await systemUtils.getSystemInfo(); const sysType = sysTypeManager.createSystemType(systemInfo.SystemName) || sysTypeManager.createDefaultSystemType(); sysType === null || sysType === void 0 ? void 0 : sysType.deviceMgrIF.setMaxDataPointsToStore(settingsManager.getSetting("maxDatapointsToStore")); return sysType; }); // Callback on connection event this._onConnectionEvent = null; } // Get instance static getInstance() { if (!ConnManager._instance) { ConnManager._instance = new ConnManager(); } return ConnManager._instance; } // Set connection event listener setConnectionEventListener(listener) { this._onConnectionEvent = listener; } // Check if connected isConnected() { return this._connector.isConnected(); } getConnector() { return this._connector; } /** * @brief Like getBleDevice but the names to ignore are passed in as an array * @param namesToIgnore Array of names to ignore * @returns A promise that resolves to a BluetoothDevice or null if no device is found */ async getBleDevicesWithGivenNamesToIgnore(namesToIgnore) { try { const dev = await navigator.bluetooth.requestDevice({ filters: [{ services: [ConnManager.RICUUID] }, { services: [ConnManager.COGUUID] }], optionalServices: [ConnManager.RICUUID, ConnManager.COGUUID], // @ts-ignore exclusionFilters: namesToIgnore.length > 0 ? namesToIgnore : undefined, }); connectedDevices.push(dev); return dev; } catch (e) { raftjs_1.RaftLog.error(`getBleDevice - failed to get device ${e}`); return null; } } async getBleDevice(uuids) { const filtersArray = uuids.map((uuid) => ({ services: [uuid] })); const namesToIgnore = []; console.log("connectedDevices", connectedDevices); [...connectedDevices].forEach((dev) => { var _a, _b; console.log("dev.name", dev.name); console.log("isDevConnected", (_a = dev.gatt) === null || _a === void 0 ? void 0 : _a.connected); const isDevConnected = (_b = dev.gatt) === null || _b === void 0 ? void 0 : _b.connected; if (isDevConnected && dev.name) { namesToIgnore.push(({ name: dev.name })); } else { connectedDevices.splice(connectedDevices.indexOf(dev), 1); } }); console.log("connectedDevices after filtering", connectedDevices); console.log("namesToIgnore", namesToIgnore); try { const dev = await navigator.bluetooth.requestDevice({ filters: filtersArray, optionalServices: [ConnManager.RICUUID, ConnManager.COGUUID], // @ts-ignore exclusionFilters: namesToIgnore.length > 0 ? namesToIgnore : undefined, }); connectedDevices.push(dev); return dev; } catch (e) { raftjs_1.RaftLog.error(`getBleDevice - failed to get device ${e}`); return null; } } // Get system type getSystemType() { return this._connector.getSystemType(); } async initializeChannel_phoneBLE() { // Hook up the connector this._connector.setEventListener((evtType, eventEnum, eventName, eventData) => { raftjs_1.RaftLog.verbose(`ConnManager - event ${eventName}`); if (this._onConnectionEvent) { this._onConnectionEvent(evtType, eventEnum, eventName, eventData); } }); ///// return this._connector.initializeChannel("PhoneBLE"); } // Connect async connect(method, locator, uuids) { this._connector.setEventListener((evtType, eventEnum, eventName, eventData) => { raftjs_1.RaftLog.verbose(`ConnManager - event ${eventName}`); if (this._onConnectionEvent) { this._onConnectionEvent(evtType, eventEnum, eventName, eventData); } }); await this._connector.initializeChannel(method); // Set the connector websocket suffix if (method === "WebBLE") { const dev = await this.getBleDevice(uuids); return this._connector.connect(dev); } return this._connector.connect(locator); } // Disconnect disconnect() { return this._connector.disconnect(); } /////////////////////////////////////////////////////////////////////////////////// /// @brief Generate a UUID for service filtering based on device serial number /// @param baseUUID Base UUID string (e.g., "aa76677e-9cfd-4626-0000-000000000000") /// @param serialNo Serial number as an ASCII string (e.g., "1234567890123456") /// @returns Modified UUID string static generateServiceFilterUUID(serialNo, baseUUID = "aa76677e-9cfd-4626-0000-000000000000") { const UUID_128_BYTES = 16; // Convert UUID string to byte array let uuidBytes = ConnManager.uuidToByteArray(baseUUID); // Convert serial number assuming it is decimal (or hex) digits to bytes let serialBytes = ConnManager.hexStringToBytes(serialNo); // Limit to 16 bytes (UUID size) const bytesToProc = Math.min(serialBytes.length, UUID_128_BYTES); // console.log(`generateServiceFilterUUID - serialBCD: ${serialBCD} bytesToProc: ${bytesToProc}`); // XOR the serial BCD bytes with the UUID bytes for (let i = 0; i < bytesToProc; i++) { uuidBytes[15 - i] ^= serialBytes[bytesToProc - 1 - i]; } // Convert back to UUID string format return ConnManager.byteArrayToUUID(uuidBytes); } ///////////////////////////////////////////////////////////////////////////// /// @brief Convert UUID string to byte array (Big Endian order) static uuidToByteArray(uuid) { return new Uint8Array(uuid.replace(/-/g, "") // Remove dashes .match(/.{1,2}/g).map(byte => parseInt(byte, 16)) // Convert hex pairs to bytes ); } ///////////////////////////////////////////////////////////////////////////// /// @brief Convert byte array back to UUID string static byteArrayToUUID(bytes) { return [...bytes] .map(b => b.toString(16).padStart(2, "0")) // Convert to hex .join("") .replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, "$1-$2-$3-$4-$5"); // Format as UUID } ///////////////////////////////////////////////////////////////////////////// /// @brief Convert an hex string to bytes /// @param hex string - e.g. "1234567890123456" -> [0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56] /// @returns byte array static hexStringToBytes(hex) { var _a; // Pad to ensure even number of characters if (hex.length % 2 !== 0) { hex = "0" + hex; } return new Uint8Array(((_a = hex.match(/.{1,2}/g)) === null || _a === void 0 ? void 0 : _a.map(byte => parseInt(byte, 16))) || []); } } // SERVICE UUIDS for external use ConnManager.RICUUID = "aa76677e-9cfd-4626-a510-0d305be57c8d"; ConnManager.COGUUID = "da903f65-d5c2-4f4d-a065-d1aade7af874"; exports.default = ConnManager; //# sourceMappingURL=ConnManager.js.map