@robotical/roboticaljs
Version:
Javascript/TS library for Robotical products
201 lines • 8.73 kB
JavaScript
"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