Skip to content

Commit

Permalink
create getAvailableDevices() and getDevicePorts()
Browse files Browse the repository at this point in the history
  • Loading branch information
JovannMC committed Jul 22, 2024
1 parent 2396ce3 commit e796f73
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 43 deletions.
101 changes: 70 additions & 31 deletions src/HaritoraX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,32 +305,6 @@ export default class HaritoraX extends EventEmitter {
com = new COM(trackerModelEnabled, heartbeatInterval);
comEnabled = true;

if (!portNames) {
log("No port names provided, attempting to get device ports...");
if (trackerModelEnabled === "wired") {
log("Wired model enabled, getting their ports...");
//const HaritoraPorts = await com.getDevicePorts("Haritora");
const HaritoraX10Ports = await com.getDevicePorts("HaritoraX 1.0");
const HaritoraX11Ports = await com.getDevicePorts("HaritoraX 1.1");
const HaritoraX11bPorts = await com.getDevicePorts("HaritoraX 1.1b");

//log(`Got Haritora ports: ${HaritoraPorts}`);
log(`Got HaritoraX 1.0 ports: ${HaritoraX10Ports}`);
log(`Got HaritoraX 1.1 ports: ${HaritoraX11Ports}`);
log(`Got HaritoraX 1.1b ports: ${HaritoraX11bPorts}`);
//portNames = HaritoraPorts.concat(HaritoraX10Ports, HaritoraX11Ports, HaritoraX11bPorts);
portNames = HaritoraX10Ports.concat(HaritoraX11Ports, HaritoraX11bPorts);
} else if (trackerModelEnabled === "wireless") {
log("Wireless model enabled, getting their dongles' ports...");
const GX6Ports = await com.getDevicePorts("GX6");
const GX2Ports = await com.getDevicePorts("GX2");

log(`Got GX6 ports: ${GX6Ports}`);
log(`Got GX2 ports: ${GX2Ports}`);
portNames = GX6Ports.concat(GX2Ports);
}
}

com.startConnection(portNames);
canProcessComData = true;
} else if (connectionMode === "bluetooth") {
Expand Down Expand Up @@ -789,6 +763,58 @@ export default class HaritoraX extends EventEmitter {
emitData(trackerName: string, port: string, portId: string, identifier: string, data: string) {
com.emit("data", trackerName, port, portId, identifier, data);
}

/**
* Gets the available devices
*
* @function getAvailableDevices
* @returns {string} The available devices to connect to/with (HaritoraX Wired/HaritoraX Wireless/GX6/GX2/Bluetooth).
*/
async getAvailableDevices(): Promise<string[]> {
let availableDevices: string[] = [];

const com = new COM("wireless", 100000);
const bluetooth = new Bluetooth();

if (await com.isDeviceAvailable()) {
const devices = await com.getAvailableDevices();
// for each device, add the device name to the available devices
devices.forEach((device) => {
if (device === "HaritoraX 1.0" || device === "HaritoraX 1.1" || device === "HaritoraX 1.1b") {
availableDevices.push("HaritoraX Wired");
} else {
availableDevices.push(device);
}
});
}
if (await bluetooth.isDeviceAvailable()) {
availableDevices.push("Bluetooth");
availableDevices.push("HaritoraX Wireless");
}

return availableDevices;
}

/**
* Gets the available ports for the specified device
*
* @function getDevicePorts
* @param {string} device - The device to get the ports for.
* @returns {string[]} The available ports for the specified device.
*/
async getDevicePorts(device: string): Promise<string[]> {
const com = new COM("wireless", 100000);

if (device === "HaritoraX Wired") {
return (
(await com.getDevicePorts("HaritoraX 1.0")) ||
(await com.getDevicePorts("HaritoraX 1.1")) ||
(await com.getDevicePorts("HaritoraX 1.1b"))
);
} else {
return await com.getDevicePorts(device);
}
}
}

function listenToDeviceEvents() {
Expand Down Expand Up @@ -1479,10 +1505,18 @@ function processBatteryData(data: string, trackerName: string, characteristic?:
const chargeStatus = Buffer.from(data, "base64").toString("hex");
let chargeStatusReadable;
switch (chargeStatus) {
case "00": chargeStatusReadable = "discharging"; break;
case "01": chargeStatusReadable = "charging"; break;
case "02": chargeStatusReadable = "charged"; break;
default: chargeStatusReadable = "unknown"; break;
case "00":
chargeStatusReadable = "discharging";
break;
case "01":
chargeStatusReadable = "charging";
break;
case "02":
chargeStatusReadable = "charged";
break;
default:
chargeStatusReadable = "unknown";
break;
}
updateAndEmitBatteryInfo(trackerName, "ChargeStatus", chargeStatusReadable);
}
Expand Down Expand Up @@ -1618,7 +1652,12 @@ async function removeActiveDevices(deviceTypeToRemove: string) {

function getTrackerSettingsFromMap(trackerName: string) {
const settings = trackerSettings.get(trackerName);
const settingsToLog = { "Sensor mode": settings[0], "FPS mode": settings[1], "Sensor auto correction": settings[2], "Ankle motion detection": settings[3] };
const settingsToLog = {
"Sensor mode": settings[0],
"FPS mode": settings[1],
"Sensor auto correction": settings[2],
"Ankle motion detection": settings[3],
};
logSettings(trackerName, settingsToLog);
return {
sensorMode: settings[0],
Expand Down
53 changes: 44 additions & 9 deletions src/mode/bluetooth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,52 @@ let allowReconnect = true;
export default class Bluetooth extends EventEmitter {
constructor() {
super();
this.setMaxListeners(1); // Prevent memory leaks
noble.on("discover", this.onDiscover.bind(this));
main = this;
log(`Initialized Bluetooth module.`);
}

async isDeviceAvailable() {
return new Promise<Boolean>((resolve) => {
let found = false;

const discoverListener = (peripheral: Peripheral) => {
if (peripheral.advertisement.localName && peripheral.advertisement.localName.startsWith("HaritoraXW-")) {
found = true;
noble.stopScanning();
cleanupListeners();
resolve(true);
}
};

const stateChangeListener = (state: string) => {
if (state === "poweredOn" && !found) {
noble.startScanning([], true);

setTimeout(() => {
if (!found) {
noble.stopScanning();
cleanupListeners();
resolve(false);
}
}, 3000);
} else {
cleanupListeners();
resolve(false);
}
};

const cleanupListeners = () => {
noble.removeListener("discover", discoverListener);
noble.removeListener("stateChange", stateChangeListener);
};

noble.on("discover", discoverListener);
noble.on("stateChange", stateChangeListener);
});
}

startConnection() {
const startScanning = () => {
try {
Expand All @@ -84,11 +125,11 @@ export default class Bluetooth extends EventEmitter {
}
}

async onDiscover(peripheral: Peripheral) {
private async onDiscover(peripheral: Peripheral) {
const {
advertisement: { localName },
} = peripheral;
if (!localName || !localName.startsWith("HaritoraX")) return;
if (!localName || !localName.startsWith("HaritoraXW-")) return;

const deviceExists = activeDevices.some((device) => device[0] === localName || device[1] === peripheral);
if (deviceExists) return;
Expand Down Expand Up @@ -313,13 +354,7 @@ function getCharacteristic(service: Service, characteristic: string): Characteri
*/

function emitData(localName: string, service: string, characteristic: string, data: any) {
main.emit(
"data",
localName,
services.get(service) || service,
characteristics.get(characteristic) || characteristic,
data
);
main.emit("data", localName, services.get(service) || service, characteristics.get(characteristic) || characteristic, data);
}

function log(message: string) {
Expand Down
39 changes: 36 additions & 3 deletions src/mode/com.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,56 @@ let heartbeatInterval: number; // in milliseconds
export default class COM extends EventEmitter {
constructor(trackerModel: string, heartbeat: number) {
super();
this.setMaxListeners(1); // Prevent memory leaks
main = this;
trackerModelEnabled = trackerModel;
heartbeatInterval = heartbeat;
log(`Initialized COM module with settings: ${trackerModelEnabled} ${heartbeatInterval}`);
}

async isDeviceAvailable() {
const ports = await Binding.list();
for (const device of devices) {
if (ports.some((port) => port.vendorId === device.vid && port.productId === device.pid)) {
return true;
}
}
}

async getAvailableDevices() {
const ports = await Binding.list();
const availableDeviceNames: Set<string> = new Set();
let gxDevicesFound = false;
for (const device of devices) {
const matchingPort = ports.find((port) => port.vendorId === device.vid && port.productId === device.pid);
if (matchingPort) {
if (device.name === "GX6" || device.name === "GX2") {
gxDevicesFound = true;
availableDeviceNames.add(device.name);
} else {
availableDeviceNames.add(device.name);
}
}
}

if (gxDevicesFound) availableDeviceNames.add("HaritoraX Wireless");

return Array.from(availableDeviceNames);
}

async getDevicePorts(device: string) {
const ports = await Binding.list();
const availablePorts = ports
.map(port => {
const deviceMatch = devices.find(deviceItem => port.vendorId === deviceItem.vid && port.productId === deviceItem.pid);
.map((port) => {
const deviceMatch = devices.find(
(deviceItem) => port.vendorId === deviceItem.vid && port.productId === deviceItem.pid
);
return {
...port,
deviceName: deviceMatch ? deviceMatch.name : undefined,
};
})
.filter(port_1 => port_1.deviceName !== undefined);
.filter((port_1) => port_1.deviceName !== undefined);
let foundPorts = [];
for (const port_2 of availablePorts) {
if (port_2.deviceName === device) foundPorts.push(port_2.path);
Expand Down

0 comments on commit e796f73

Please sign in to comment.