From c6cd810966e1c958a5b9df4835f7045cdaba452a Mon Sep 17 00:00:00 2001 From: Landry Date: Thu, 3 Aug 2023 11:23:37 -0500 Subject: [PATCH 01/81] merge in main --- package-lock.json | 121 ++++--- packages/control-hub/package.json | 18 + packages/control-hub/src/index.ts | 0 .../control-hub/src/internal/ControlHub.ts | 341 ++++++++++++++++++ .../control-hub/src/internal/discovery.ts | 18 + packages/control-hub/tsconfig.json | 8 + packages/core/src/RevHubType.ts | 1 + 7 files changed, 462 insertions(+), 45 deletions(-) create mode 100644 packages/control-hub/package.json create mode 100644 packages/control-hub/src/index.ts create mode 100644 packages/control-hub/src/internal/ControlHub.ts create mode 100644 packages/control-hub/src/internal/discovery.ts create mode 100644 packages/control-hub/tsconfig.json diff --git a/package-lock.json b/package-lock.json index 719f3fff..5ae777c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,6 +3,7 @@ "lockfileVersion": 2, "requires": true, "packages": { + "packages": {}, "": { "name": "root", "workspaces": [ @@ -1566,20 +1567,6 @@ "node": ">=10" } }, - "node_modules/@nrwl/nx-win32-x64-msvc": { - "version": "15.9.4", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@nrwl/tao": { "version": "16.2.1", "dev": true, @@ -1591,20 +1578,6 @@ "tao": "index.js" } }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "16.2.1", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@octokit/auth-token": { "version": "3.0.3", "dev": true, @@ -1779,6 +1752,10 @@ "dev": true, "license": "MIT" }, + "node_modules/@rev-robotics/control-hub": { + "resolved": "packages/control-hub", + "link": true + }, "node_modules/@rev-robotics/expansion-hub": { "resolved": "packages/expansion-hub", "link": true @@ -4104,6 +4081,13 @@ "node": ">=0.10.0" } }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/jake": { "version": "10.8.5", "dev": true, @@ -5153,10 +5137,6 @@ "node": ">=10" } }, - "node_modules/node-addon-api": { - "version": "6.1.0", - "license": "MIT" - }, "node_modules/node-fetch": { "version": "2.6.9", "dev": true, @@ -7485,6 +7465,26 @@ "node": ">=6" } }, + "node_modules/ws": { + "version": "8.13.0", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xtend": { "version": "4.0.2", "dev": true, @@ -7539,6 +7539,19 @@ "node": ">=10" } }, + "packages/control-hub": { + "name": "@rev-robotics/control-hub", + "version": "0.1.0", + "dependencies": { + "@rev-robotics/rhsplib": "*", + "isomorphic-ws": "^5.0.0", + "serialport": "^10.5.0" + }, + "devDependencies": { + "@types/node": "^16.18.18", + "typescript": "^5.0.2" + } + }, "packages/core": { "name": "@rev-robotics/rev-hub-core", "version": "1.0.0", @@ -7577,6 +7590,11 @@ "typescript": "^5.0.2" } }, + "packages/rhsplib/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "packages/sample": { "name": "rev-hub-cli", "version": "1.0.0", @@ -8718,11 +8736,6 @@ } } }, - "@nrwl/nx-win32-x64-msvc": { - "version": "15.9.4", - "dev": true, - "optional": true - }, "@nrwl/tao": { "version": "16.2.1", "dev": true, @@ -8730,11 +8743,6 @@ "nx": "16.2.1" } }, - "@nx/nx-win32-x64-msvc": { - "version": "16.2.1", - "dev": true, - "optional": true - }, "@octokit/auth-token": { "version": "3.0.3", "dev": true, @@ -8853,6 +8861,16 @@ } } }, + "@rev-robotics/control-hub": { + "version": "file:packages/control-hub", + "requires": { + "@rev-robotics/rhsplib": "*", + "@types/node": "^16.18.18", + "isomorphic-ws": "^5.0.0", + "serialport": "^10.5.0", + "typescript": "^5.0.2" + } + }, "@rev-robotics/expansion-hub": { "version": "file:packages/expansion-hub", "requires": { @@ -8880,6 +8898,13 @@ "node-gyp-build": "^4.6.0", "prebuildify": "^5.0.1", "typescript": "^5.0.2" + }, + "dependencies": { + "node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + } } }, "@serialport/binding-mock": { @@ -10354,6 +10379,10 @@ "version": "3.0.1", "dev": true }, + "isomorphic-ws": { + "version": "5.0.0", + "requires": {} + }, "jake": { "version": "10.8.5", "dev": true, @@ -11050,9 +11079,6 @@ "semver": "^7.3.5" } }, - "node-addon-api": { - "version": "6.1.0" - }, "node-fetch": { "version": "2.6.9", "dev": true, @@ -12564,6 +12590,11 @@ } } }, + "ws": { + "version": "8.13.0", + "peer": true, + "requires": {} + }, "xtend": { "version": "4.0.2", "dev": true diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json new file mode 100644 index 00000000..07e9d25b --- /dev/null +++ b/packages/control-hub/package.json @@ -0,0 +1,18 @@ +{ + "name": "@rev-robotics/control-hub", + "version": "0.1.0", + "description": "High level library for REV control hub", + "main": "dist/index.js", + "dependencies": { + "serialport": "^10.5.0", + "isomorphic-ws": "^5.0.0", + "@rev-robotics/rhsplib": "*" + }, + "devDependencies": { + "@types/node": "^16.18.18", + "typescript": "^5.0.2" + }, + "scripts": { + "build": "tsc" + } +} \ No newline at end of file diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts new file mode 100644 index 00000000..0d6f24df --- /dev/null +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -0,0 +1,341 @@ +import { + ExpansionHub, + ParentRevHub, + RevHub, +} from "@rev-robotics/expansion-hub"; +import { RevHubType } from "@rev-robotics/expansion-hub/dist/RevHubType"; +import { + BulkInputData, + DebugGroup, + DIODirection, + I2CReadStatus, + I2CSpeedCode, + I2CWriteStatus, + LEDPattern, + ModuleInterface, + ModuleStatus, + PIDCoefficients, + RGB, + VerbosityLevel, + Version, +} from "@rev-robotics/rhsplib"; + +export class ControlHub implements ExpansionHub { + readonly isOpen: boolean = true; + readonly moduleAddress: number = 0; + responseTimeoutMs: number = 0; + type: RevHubType = RevHubType.ControlHub; + + async open() {} + + close(): void {} + + getADC(): Promise { + return Promise.resolve(0); + } + + async getBulkInputData(): Promise { + throw new Error("not implemented"); + } + + getDigitalAllInputs(): Promise { + throw new Error("not implemented"); + } + + async getDigitalDirection(dioPin: number): Promise { + throw new Error("not implemented"); + } + + getDigitalSingleInput(dioPin: number): Promise { + throw new Error("not implemented"); + } + + getFTDIResetControl(): Promise { + throw new Error("not implemented"); + } + + getI2CChannelConfiguration(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getI2CReadStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getI2CWriteStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getInterfacePacketID( + interfaceName: string, + functionNumber: number + ): Promise { + return Promise.resolve(0); + } + + getModuleLEDColor(): Promise { + throw new Error("not implemented"); + } + + getModuleLEDPattern(): Promise { + throw new Error("not implemented"); + } + + getModuleStatus(clearStatusAfterResponse: boolean): Promise { + throw new Error("not implemented"); + } + + getMotorAtTarget(motorChannel: number): Promise { + return Promise.resolve(false); + } + + getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getMotorChannelEnable(motorChannel: number): Promise { + return Promise.resolve(false); + } + + getMotorChannelMode( + motorChannel: number + ): Promise<{ motorMode: number; floatAtZero: boolean }> { + return Promise.resolve({ floatAtZero: false, motorMode: 0 }); + } + + getMotorConstantPower(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getMotorEncoderPosition(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getMotorPIDCoefficients( + motorChannel: number, + motorMode: number + ): Promise { + throw new Error("not implemented"); + } + + getMotorTargetPosition( + motorChannel: number + ): Promise<{ targetPosition: number; targetTolerance: number }> { + return Promise.resolve({ targetPosition: 0, targetTolerance: 0 }); + } + + getMotorTargetVelocity(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getPhoneChargeControl(): Promise { + return Promise.resolve(false); + } + + getServoConfiguration(servoChannel: number): Promise { + return Promise.resolve(0); + } + + getServoEnable(servoChannel: number): Promise { + return Promise.resolve(false); + } + + getServoPulseWidth(servoChannel: number): Promise { + return Promise.resolve(0); + } + + injectDataLogHint(hintText: string): Promise { + throw new Error("not implemented"); + } + + isExpansionHub(): this is ExpansionHub { + throw new Error("not implemented"); + } + + isParent(): this is ParentRevHub { + throw new Error("not implemented"); + } + + on(eventName: "error", listener: (error: Error) => void): RevHub { + throw new Error("not implemented"); + } + + queryInterface(interfaceName: string): Promise { + throw new Error("not implemented"); + } + + readI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number + ): Promise { + throw new Error("not implemented"); + } + + readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + throw new Error("not implemented"); + } + + readVersion(): Promise { + throw new Error("not implemented"); + } + + readVersionString(): Promise { + return Promise.resolve(""); + } + + resetMotorEncoder(motorChannel: number): Promise { + throw new Error("not implemented"); + } + + sendFailSafe(): Promise { + throw new Error("not implemented"); + } + + sendKeepAlive(): Promise { + throw new Error("not implemented"); + } + + sendReadCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + sendWriteCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + setDebugLogLevel( + debugGroup: DebugGroup, + verbosityLevel: VerbosityLevel + ): Promise { + throw new Error("not implemented"); + } + + setDigitalAllOutputs(bitPackedField: number): Promise { + throw new Error("not implemented"); + } + + setDigitalDirection(dioPin: number, direction: DIODirection): Promise { + throw new Error("not implemented"); + } + + setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { + throw new Error("not implemented"); + } + + setFTDIResetControl(ftdiResetControl: boolean): Promise { + throw new Error("not implemented"); + } + + setI2CChannelConfiguration( + i2cChannel: number, + speedCode: I2CSpeedCode + ): Promise { + throw new Error("not implemented"); + } + + setModuleLEDColor(red: number, green: number, blue: number): Promise { + throw new Error("not implemented"); + } + + setModuleLEDPattern(ledPattern: LEDPattern): Promise { + throw new Error("not implemented"); + } + + setMotorChannelCurrentAlertLevel( + motorChannel: number, + currentLimit_mA: number + ): Promise { + throw new Error("not implemented"); + } + + setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { + throw new Error("not implemented"); + } + + setMotorChannelMode( + motorChannel: number, + motorMode: number, + floatAtZero: boolean + ): Promise { + throw new Error("not implemented"); + } + + setMotorConstantPower( + motorChannel: number, + powerLevel: number + ): Promise { + throw new Error("not implemented"); + } + + setMotorPIDCoefficients( + motorChannel: number, + motorMode: number, + pid: PIDCoefficients + ): Promise { + throw new Error("not implemented"); + } + + setMotorTargetPosition( + motorChannel: number, + targetPosition_counts: number, + targetTolerance_counts: number + ): Promise { + throw new Error("not implemented"); + } + + setMotorTargetVelocity( + motorChannel: number, + velocity_cps: number + ): Promise { + throw new Error("not implemented"); + } + + setNewModuleAddress(newModuleAddress: number): Promise { + throw new Error("not implemented"); + } + + setPhoneChargeControl(chargeEnable: boolean): Promise { + throw new Error("not implemented"); + } + + setServoConfiguration( + servoChannel: number, + framePeriod: number + ): Promise { + throw new Error("not implemented"); + } + + setServoEnable(servoChannel: number, enable: boolean): Promise { + throw new Error("not implemented"); + } + + setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { + throw new Error("not implemented"); + } + + writeI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + bytes: number[] + ): Promise { + throw new Error("not implemented"); + } + + writeI2CReadMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + startAddress: number + ): Promise { + throw new Error("not implemented"); + } + + writeI2CSingleByte( + i2cChannel: number, + slaveAddress: number, + byte: number + ): Promise { + throw new Error("not implemented"); + } +} diff --git a/packages/control-hub/src/internal/discovery.ts b/packages/control-hub/src/internal/discovery.ts new file mode 100644 index 00000000..c58d2d5d --- /dev/null +++ b/packages/control-hub/src/internal/discovery.ts @@ -0,0 +1,18 @@ +import { ControlHub } from "./ControlHub"; + +export async function getConnectedControlHub(): Promise< + ControlHub | undefined +> { + try { + return await createControlHub(); + } catch (e: any) { + return undefined; + } +} + +async function createControlHub(): Promise { + let hub = new ControlHub(); + await hub.open(); + + return hub; +} diff --git a/packages/control-hub/tsconfig.json b/packages/control-hub/tsconfig.json new file mode 100644 index 00000000..4a3682c7 --- /dev/null +++ b/packages/control-hub/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src", + "target": "es2017" + } +} diff --git a/packages/core/src/RevHubType.ts b/packages/core/src/RevHubType.ts index c68871a1..de4220b4 100644 --- a/packages/core/src/RevHubType.ts +++ b/packages/core/src/RevHubType.ts @@ -1,3 +1,4 @@ export enum RevHubType { ExpansionHub, + ControlHub, } From 17b4a2bfd3214abab611899ff3d0a7ab07cee983 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 25 May 2023 13:58:40 -0500 Subject: [PATCH 02/81] Try to connect to control hub --- packages/control-hub/package.json | 1 + .../control-hub/src/internal/ControlHub.ts | 21 ++++++++++++++++++- .../control-hub/src/internal/discovery.ts | 5 +++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 07e9d25b..fedd1e66 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -6,6 +6,7 @@ "dependencies": { "serialport": "^10.5.0", "isomorphic-ws": "^5.0.0", + "axios":"^1.4.0", "@rev-robotics/rhsplib": "*" }, "devDependencies": { diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 0d6f24df..fc3873c8 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -19,14 +19,33 @@ import { VerbosityLevel, Version, } from "@rev-robotics/rhsplib"; +import axios from "axios"; export class ControlHub implements ExpansionHub { readonly isOpen: boolean = true; readonly moduleAddress: number = 0; responseTimeoutMs: number = 0; type: RevHubType = RevHubType.ControlHub; + webSocketConnection?: WebSocket; - async open() {} + async open() { + this.webSocketConnection = new WebSocket("ws://192.168.43.1:8081"); + } + + async isConnected(): Promise { + try { + let response = await axios.get("http://192.168.43.1:8080/js/rcInfo.json"); + if(response.data) { + let rcInfo = JSON.parse(response.data); + console.log(rcInfo); + return rcInfo.webSocketApiVersion == "1"; + } + + return false; + } catch (e) { + return false; + } + } close(): void {} diff --git a/packages/control-hub/src/internal/discovery.ts b/packages/control-hub/src/internal/discovery.ts index c58d2d5d..f8311540 100644 --- a/packages/control-hub/src/internal/discovery.ts +++ b/packages/control-hub/src/internal/discovery.ts @@ -12,6 +12,11 @@ export async function getConnectedControlHub(): Promise< async function createControlHub(): Promise { let hub = new ControlHub(); + + if(!await hub.isConnected()) { + throw new Error("Hub is not connected via WiFi"); + } + await hub.open(); return hub; From 019dddf4f2c10d83bf9ba0da9f142a14c944555e Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 25 May 2023 14:12:02 -0500 Subject: [PATCH 03/81] Try to connect to control hub --- packages/control-hub/src/{internal => }/discovery.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/control-hub/src/{internal => }/discovery.ts (100%) diff --git a/packages/control-hub/src/internal/discovery.ts b/packages/control-hub/src/discovery.ts similarity index 100% rename from packages/control-hub/src/internal/discovery.ts rename to packages/control-hub/src/discovery.ts From 57d3506bfa4800c4491fca1b3b7bdaf606f4061d Mon Sep 17 00:00:00 2001 From: Landry Date: Thu, 3 Aug 2023 11:40:00 -0500 Subject: [PATCH 04/81] merge in main --- package-lock.json | 83 +- packages/control-hub/src/discovery.ts | 6 +- packages/control-hub/src/index.ts | 2 + .../control-hub/src/internal/ControlHub.ts | 750 +++++++++--------- packages/control-hub/tsconfig.json | 1 + packages/sample/package.json | 4 + packages/sample/src/command/list.ts | 21 +- 7 files changed, 464 insertions(+), 403 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5ae777c2..0091596d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,7 +3,6 @@ "lockfileVersion": 2, "requires": true, "packages": { - "packages": {}, "": { "name": "root", "workspaces": [ @@ -1955,6 +1954,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "dev": true, @@ -2156,7 +2164,6 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "dev": true, "license": "MIT" }, "node_modules/at-least-node": { @@ -2169,7 +2176,6 @@ }, "node_modules/axios": { "version": "1.4.0", - "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.0", @@ -2526,7 +2532,6 @@ }, "node_modules/combined-stream": { "version": "1.0.8", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -2855,7 +2860,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -3218,7 +3222,6 @@ }, "node_modules/follow-redirects": { "version": "1.15.2", - "dev": true, "funding": [ { "type": "individual", @@ -3237,7 +3240,6 @@ }, "node_modules/form-data": { "version": "4.0.0", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -4884,7 +4886,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -4892,7 +4893,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -5137,6 +5137,11 @@ "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node_modules/node-fetch": { "version": "2.6.9", "dev": true, @@ -6199,7 +6204,6 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "dev": true, "license": "MIT" }, "node_modules/pump": { @@ -7468,7 +7472,6 @@ "node_modules/ws": { "version": "8.13.0", "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -7544,6 +7547,7 @@ "version": "0.1.0", "dependencies": { "@rev-robotics/rhsplib": "*", + "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", "serialport": "^10.5.0" }, @@ -7590,20 +7594,19 @@ "typescript": "^5.0.2" } }, - "packages/rhsplib/node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" - }, "packages/sample": { "name": "rev-hub-cli", "version": "1.0.0", "dependencies": { "@rev-robotics/expansion-hub": "^1.0.0", - "commander": "^10.0.1" + "commander": "^10.0.1", + "ws": "8.13.0" }, "bin": { "rev-hub-cli": "revhub" + }, + "devDependencies": { + "@types/ws": "^8.5.4" } } }, @@ -8866,6 +8869,7 @@ "requires": { "@rev-robotics/rhsplib": "*", "@types/node": "^16.18.18", + "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", "serialport": "^10.5.0", "typescript": "^5.0.2" @@ -8898,13 +8902,6 @@ "node-gyp-build": "^4.6.0", "prebuildify": "^5.0.1", "typescript": "^5.0.2" - }, - "dependencies": { - "node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" - } } }, "@serialport/binding-mock": { @@ -8996,6 +8993,15 @@ "version": "4.0.0", "dev": true }, + "@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@yarnpkg/lockfile": { "version": "1.1.0", "dev": true @@ -9127,8 +9133,7 @@ "dev": true }, "asynckit": { - "version": "0.4.0", - "dev": true + "version": "0.4.0" }, "at-least-node": { "version": "1.0.0", @@ -9136,7 +9141,6 @@ }, "axios": { "version": "1.4.0", - "dev": true, "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -9363,7 +9367,6 @@ }, "combined-stream": { "version": "1.0.8", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -9581,8 +9584,7 @@ "dev": true }, "delayed-stream": { - "version": "1.0.0", - "dev": true + "version": "1.0.0" }, "delegates": { "version": "1.0.0", @@ -9821,12 +9823,10 @@ "dev": true }, "follow-redirects": { - "version": "1.15.2", - "dev": true + "version": "1.15.2" }, "form-data": { "version": "4.0.0", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -10920,12 +10920,10 @@ } }, "mime-db": { - "version": "1.52.0", - "dev": true + "version": "1.52.0" }, "mime-types": { "version": "2.1.35", - "dev": true, "requires": { "mime-db": "1.52.0" } @@ -11079,6 +11077,11 @@ "semver": "^7.3.5" } }, + "node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node-fetch": { "version": "2.6.9", "dev": true, @@ -11771,8 +11774,7 @@ "dev": true }, "proxy-from-env": { - "version": "1.1.0", - "dev": true + "version": "1.1.0" }, "pump": { "version": "3.0.0", @@ -11987,7 +11989,9 @@ "version": "file:packages/sample", "requires": { "@rev-robotics/expansion-hub": "^1.0.0", - "commander": "^10.0.1" + "@types/ws": "^8.5.4", + "commander": "^10.0.1", + "ws": "8.13.0" } }, "rimraf": { @@ -12592,7 +12596,6 @@ }, "ws": { "version": "8.13.0", - "peer": true, "requires": {} }, "xtend": { diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index f8311540..53ce4169 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -1,11 +1,12 @@ -import { ControlHub } from "./ControlHub"; +import { ControlHub } from "./internal/ControlHub"; -export async function getConnectedControlHub(): Promise< +export async function openConnectedControlHub(): Promise< ControlHub | undefined > { try { return await createControlHub(); } catch (e: any) { + console.log(e); return undefined; } } @@ -14,6 +15,7 @@ async function createControlHub(): Promise { let hub = new ControlHub(); if(!await hub.isConnected()) { + console.log("Hub not connected") throw new Error("Hub is not connected via WiFi"); } diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index e69de29b..e5d405df 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -0,0 +1,2 @@ + +export * from './discovery'; \ No newline at end of file diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index fc3873c8..0da915ae 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -1,360 +1,404 @@ -import { - ExpansionHub, - ParentRevHub, - RevHub, -} from "@rev-robotics/expansion-hub"; +import { ExpansionHub, ParentRevHub, RevHub } from "@rev-robotics/expansion-hub"; import { RevHubType } from "@rev-robotics/expansion-hub/dist/RevHubType"; import { - BulkInputData, - DebugGroup, - DIODirection, - I2CReadStatus, - I2CSpeedCode, - I2CWriteStatus, - LEDPattern, - ModuleInterface, - ModuleStatus, - PIDCoefficients, - RGB, - VerbosityLevel, - Version, + BulkInputData, + DebugGroup, + DIODirection, + I2CReadStatus, + I2CSpeedCode, + I2CWriteStatus, + LEDPattern, + ModuleInterface, + ModuleStatus, + PIDCoefficients, + RGB, + VerbosityLevel, + Version, } from "@rev-robotics/rhsplib"; import axios from "axios"; +import WebSocket from "isomorphic-ws"; export class ControlHub implements ExpansionHub { - readonly isOpen: boolean = true; - readonly moduleAddress: number = 0; - responseTimeoutMs: number = 0; - type: RevHubType = RevHubType.ControlHub; - webSocketConnection?: WebSocket; - - async open() { - this.webSocketConnection = new WebSocket("ws://192.168.43.1:8081"); - } - - async isConnected(): Promise { - try { - let response = await axios.get("http://192.168.43.1:8080/js/rcInfo.json"); - if(response.data) { - let rcInfo = JSON.parse(response.data); - console.log(rcInfo); - return rcInfo.webSocketApiVersion == "1"; - } - - return false; - } catch (e) { - return false; - } - } - - close(): void {} - - getADC(): Promise { - return Promise.resolve(0); - } - - async getBulkInputData(): Promise { - throw new Error("not implemented"); - } - - getDigitalAllInputs(): Promise { - throw new Error("not implemented"); - } - - async getDigitalDirection(dioPin: number): Promise { - throw new Error("not implemented"); - } - - getDigitalSingleInput(dioPin: number): Promise { - throw new Error("not implemented"); - } - - getFTDIResetControl(): Promise { - throw new Error("not implemented"); - } - - getI2CChannelConfiguration(i2cChannel: number): Promise { - throw new Error("not implemented"); - } - - getI2CReadStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); - } - - getI2CWriteStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); - } - - getInterfacePacketID( - interfaceName: string, - functionNumber: number - ): Promise { - return Promise.resolve(0); - } - - getModuleLEDColor(): Promise { - throw new Error("not implemented"); - } - - getModuleLEDPattern(): Promise { - throw new Error("not implemented"); - } - - getModuleStatus(clearStatusAfterResponse: boolean): Promise { - throw new Error("not implemented"); - } - - getMotorAtTarget(motorChannel: number): Promise { - return Promise.resolve(false); - } - - getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { - return Promise.resolve(0); - } - - getMotorChannelEnable(motorChannel: number): Promise { - return Promise.resolve(false); - } - - getMotorChannelMode( - motorChannel: number - ): Promise<{ motorMode: number; floatAtZero: boolean }> { - return Promise.resolve({ floatAtZero: false, motorMode: 0 }); - } - - getMotorConstantPower(motorChannel: number): Promise { - return Promise.resolve(0); - } - - getMotorEncoderPosition(motorChannel: number): Promise { - return Promise.resolve(0); - } - - getMotorPIDCoefficients( - motorChannel: number, - motorMode: number - ): Promise { - throw new Error("not implemented"); - } - - getMotorTargetPosition( - motorChannel: number - ): Promise<{ targetPosition: number; targetTolerance: number }> { - return Promise.resolve({ targetPosition: 0, targetTolerance: 0 }); - } - - getMotorTargetVelocity(motorChannel: number): Promise { - return Promise.resolve(0); - } - - getPhoneChargeControl(): Promise { - return Promise.resolve(false); - } - - getServoConfiguration(servoChannel: number): Promise { - return Promise.resolve(0); - } - - getServoEnable(servoChannel: number): Promise { - return Promise.resolve(false); - } - - getServoPulseWidth(servoChannel: number): Promise { - return Promise.resolve(0); - } - - injectDataLogHint(hintText: string): Promise { - throw new Error("not implemented"); - } - - isExpansionHub(): this is ExpansionHub { - throw new Error("not implemented"); - } - - isParent(): this is ParentRevHub { - throw new Error("not implemented"); - } - - on(eventName: "error", listener: (error: Error) => void): RevHub { - throw new Error("not implemented"); - } - - queryInterface(interfaceName: string): Promise { - throw new Error("not implemented"); - } - - readI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number - ): Promise { - throw new Error("not implemented"); - } - - readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { - throw new Error("not implemented"); - } - - readVersion(): Promise { - throw new Error("not implemented"); - } - - readVersionString(): Promise { - return Promise.resolve(""); - } - - resetMotorEncoder(motorChannel: number): Promise { - throw new Error("not implemented"); - } - - sendFailSafe(): Promise { - throw new Error("not implemented"); - } - - sendKeepAlive(): Promise { - throw new Error("not implemented"); - } - - sendReadCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); - } - - sendWriteCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); - } - - setDebugLogLevel( - debugGroup: DebugGroup, - verbosityLevel: VerbosityLevel - ): Promise { - throw new Error("not implemented"); - } - - setDigitalAllOutputs(bitPackedField: number): Promise { - throw new Error("not implemented"); - } - - setDigitalDirection(dioPin: number, direction: DIODirection): Promise { - throw new Error("not implemented"); - } - - setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { - throw new Error("not implemented"); - } - - setFTDIResetControl(ftdiResetControl: boolean): Promise { - throw new Error("not implemented"); - } - - setI2CChannelConfiguration( - i2cChannel: number, - speedCode: I2CSpeedCode - ): Promise { - throw new Error("not implemented"); - } - - setModuleLEDColor(red: number, green: number, blue: number): Promise { - throw new Error("not implemented"); - } - - setModuleLEDPattern(ledPattern: LEDPattern): Promise { - throw new Error("not implemented"); - } - - setMotorChannelCurrentAlertLevel( - motorChannel: number, - currentLimit_mA: number - ): Promise { - throw new Error("not implemented"); - } - - setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { - throw new Error("not implemented"); - } - - setMotorChannelMode( - motorChannel: number, - motorMode: number, - floatAtZero: boolean - ): Promise { - throw new Error("not implemented"); - } - - setMotorConstantPower( - motorChannel: number, - powerLevel: number - ): Promise { - throw new Error("not implemented"); - } - - setMotorPIDCoefficients( - motorChannel: number, - motorMode: number, - pid: PIDCoefficients - ): Promise { - throw new Error("not implemented"); - } - - setMotorTargetPosition( - motorChannel: number, - targetPosition_counts: number, - targetTolerance_counts: number - ): Promise { - throw new Error("not implemented"); - } - - setMotorTargetVelocity( - motorChannel: number, - velocity_cps: number - ): Promise { - throw new Error("not implemented"); - } - - setNewModuleAddress(newModuleAddress: number): Promise { - throw new Error("not implemented"); - } - - setPhoneChargeControl(chargeEnable: boolean): Promise { - throw new Error("not implemented"); - } - - setServoConfiguration( - servoChannel: number, - framePeriod: number - ): Promise { - throw new Error("not implemented"); - } - - setServoEnable(servoChannel: number, enable: boolean): Promise { - throw new Error("not implemented"); - } - - setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { - throw new Error("not implemented"); - } - - writeI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - bytes: number[] - ): Promise { - throw new Error("not implemented"); - } - - writeI2CReadMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number, - startAddress: number - ): Promise { - throw new Error("not implemented"); - } - - writeI2CSingleByte( - i2cChannel: number, - slaveAddress: number, - byte: number - ): Promise { - throw new Error("not implemented"); - } + readonly isOpen: boolean = true; + moduleAddress: number = 0; + responseTimeoutMs: number = 0; + type: RevHubType = RevHubType.ControlHub; + webSocketConnection!: WebSocket; + + keyGenerator = 0; + currentActiveCommands = new Map< + any, + (response: any | undefined, error: any | undefined) => void + >(); + + async open(): Promise { + this.webSocketConnection = new WebSocket("ws://192.168.43.1:8081"); + + this.webSocketConnection.on("message", (data) => { + let rawMessage = JSON.parse(data.toString()); + + if (rawMessage.key !== undefined) { + let key = rawMessage.key; + let callback = this.currentActiveCommands.get(key); + + let response = rawMessage.response + ? JSON.parse(rawMessage.response) + : undefined; + let error = rawMessage.error ? JSON.parse(rawMessage.error) : undefined; + + if (callback) { + callback(response, error); + } + } + }); + + return new Promise((resolve, reject) => { + this.webSocketConnection.on("open", async () => { + this.moduleAddress = await this.sendCommand("getModuleAddress", {}); + resolve(); + }); + }); + } + + async isConnected(): Promise { + try { + let response = await axios.get("http://192.168.43.1:8080/js/rcInfo.json", { + timeout: 1000, + }); + if (response.data) { + return true; + //return response.data.webSocketApiVersion === "1"; + } + + return false; + } catch (e) { + console.log(e); + return false; + } + } + + close(): void {} + + getADC(): Promise { + return Promise.resolve(0); + } + + async getBulkInputData(): Promise { + throw new Error("not implemented"); + } + + getDigitalAllInputs(): Promise { + throw new Error("not implemented"); + } + + async getDigitalDirection(dioPin: number): Promise { + throw new Error("not implemented"); + } + + getDigitalSingleInput(dioPin: number): Promise { + throw new Error("not implemented"); + } + + getFTDIResetControl(): Promise { + throw new Error("not implemented"); + } + + getI2CChannelConfiguration(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getI2CReadStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getI2CWriteStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getInterfacePacketID(interfaceName: string, functionNumber: number): Promise { + return Promise.resolve(0); + } + + getModuleLedColor(): Promise { + throw new Error("not implemented"); + } + + getModuleLedPattern(): Promise { + throw new Error("not implemented"); + } + + getModuleStatus(clearStatusAfterResponse: boolean): Promise { + throw new Error("not implemented"); + } + + getMotorAtTarget(motorChannel: number): Promise { + return Promise.resolve(false); + } + + getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getMotorChannelEnable(motorChannel: number): Promise { + return Promise.resolve(false); + } + + getMotorChannelMode( + motorChannel: number, + ): Promise<{ motorMode: number; floatAtZero: boolean }> { + return Promise.resolve({ floatAtZero: false, motorMode: 0 }); + } + + getMotorConstantPower(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getMotorEncoderPosition(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getMotorPIDCoefficients( + motorChannel: number, + motorMode: number, + ): Promise { + throw new Error("not implemented"); + } + + getMotorTargetPosition( + motorChannel: number, + ): Promise<{ targetPosition: number; targetTolerance: number }> { + return Promise.resolve({ targetPosition: 0, targetTolerance: 0 }); + } + + getMotorTargetVelocity(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getPhoneChargeControl(): Promise { + return Promise.resolve(false); + } + + getServoConfiguration(servoChannel: number): Promise { + return Promise.resolve(0); + } + + getServoEnable(servoChannel: number): Promise { + return Promise.resolve(false); + } + + getServoPulseWidth(servoChannel: number): Promise { + return Promise.resolve(0); + } + + injectDataLogHint(hintText: string): Promise { + throw new Error("not implemented"); + } + + isExpansionHub(): this is ExpansionHub { + throw new Error("not implemented"); + } + + isParent(): this is ParentRevHub { + throw new Error("not implemented"); + } + + on(eventName: "error", listener: (error: Error) => void): RevHub { + throw new Error("not implemented"); + } + + queryInterface(interfaceName: string): Promise { + throw new Error("not implemented"); + } + + readI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + ): Promise { + throw new Error("not implemented"); + } + + readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + throw new Error("not implemented"); + } + + readVersion(): Promise { + throw new Error("not implemented"); + } + + readVersionString(): Promise { + return Promise.resolve(""); + } + + resetMotorEncoder(motorChannel: number): Promise { + throw new Error("not implemented"); + } + + sendFailSafe(): Promise { + throw new Error("not implemented"); + } + + sendKeepAlive(): Promise { + throw new Error("not implemented"); + } + + sendReadCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + sendWriteCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + setDebugLogLevel( + debugGroup: DebugGroup, + verbosityLevel: VerbosityLevel, + ): Promise { + throw new Error("not implemented"); + } + + setDigitalAllOutputs(bitPackedField: number): Promise { + throw new Error("not implemented"); + } + + setDigitalDirection(dioPin: number, direction: DIODirection): Promise { + throw new Error("not implemented"); + } + + setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { + throw new Error("not implemented"); + } + + setFTDIResetControl(ftdiResetControl: boolean): Promise { + throw new Error("not implemented"); + } + + setI2CChannelConfiguration( + i2cChannel: number, + speedCode: I2CSpeedCode, + ): Promise { + throw new Error("not implemented"); + } + + setModuleLedColor(red: number, green: number, blue: number): Promise { + throw new Error("not implemented"); + } + + setModuleLedPattern(ledPattern: LEDPattern): Promise { + throw new Error("not implemented"); + } + + setMotorChannelCurrentAlertLevel( + motorChannel: number, + currentLimit_mA: number, + ): Promise { + throw new Error("not implemented"); + } + + setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { + throw new Error("not implemented"); + } + + setMotorChannelMode( + motorChannel: number, + motorMode: number, + floatAtZero: boolean, + ): Promise { + throw new Error("not implemented"); + } + + setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { + throw new Error("not implemented"); + } + + setMotorPIDCoefficients( + motorChannel: number, + motorMode: number, + pid: PIDCoefficients, + ): Promise { + throw new Error("not implemented"); + } + + setMotorTargetPosition( + motorChannel: number, + targetPosition_counts: number, + targetTolerance_counts: number, + ): Promise { + throw new Error("not implemented"); + } + + setMotorTargetVelocity(motorChannel: number, velocity_cps: number): Promise { + throw new Error("not implemented"); + } + + setNewModuleAddress(newModuleAddress: number): Promise { + throw new Error("not implemented"); + } + + setPhoneChargeControl(chargeEnable: boolean): Promise { + throw new Error("not implemented"); + } + + setServoConfiguration(servoChannel: number, framePeriod: number): Promise { + throw new Error("not implemented"); + } + + setServoEnable(servoChannel: number, enable: boolean): Promise { + throw new Error("not implemented"); + } + + setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { + throw new Error("not implemented"); + } + + writeI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + bytes: number[], + ): Promise { + throw new Error("not implemented"); + } + + writeI2CReadMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + startAddress: number, + ): Promise { + throw new Error("not implemented"); + } + + writeI2CSingleByte( + i2cChannel: number, + slaveAddress: number, + byte: number, + ): Promise { + throw new Error("not implemented"); + } + + async sendCommand(type: string, params: P): Promise { + let key = 0; + let messagePayload = { + key: key, + commandPayload: JSON.stringify(params), + }; + let payload = { + namespace: "ManualControl", + type: type, + payload: JSON.stringify(messagePayload), + }; + this.webSocketConnection?.send(JSON.stringify(payload)); + + return new Promise((resolve, reject) => { + this.currentActiveCommands.set(key, (response, error) => { + if (response !== undefined) { + resolve(response); + } else { + let e = new Error(); + Object.assign(e, error); + reject(e); + } + }); + }); + } } diff --git a/packages/control-hub/tsconfig.json b/packages/control-hub/tsconfig.json index 4a3682c7..11324309 100644 --- a/packages/control-hub/tsconfig.json +++ b/packages/control-hub/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + "esModuleInterop": true, "outDir": "./dist", "rootDir": "./src", "target": "es2017" diff --git a/packages/sample/package.json b/packages/sample/package.json index 3bcfbec8..07f075fb 100644 --- a/packages/sample/package.json +++ b/packages/sample/package.json @@ -8,8 +8,12 @@ "type": "module", "dependencies": { "@rev-robotics/expansion-hub": "^1.0.0", + "ws": "8.13.0", "commander": "^10.0.1" }, + "devDependencies": { + "@types/ws": "^8.5.4" + }, "scripts": { "build": "tsc", "motor": "node dist/main.js motor power 1 0.60", diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 6a18dcd6..24d96e5c 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,7 +1,15 @@ import { hubHierarchyToString } from "../HubStringify.js"; -import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import { openConnectedControlHub } from "@rev-robotics/control-hub"; +import {ExpansionHub} from "@rev-robotics/rev-hub-core"; -export async function list(hubs: ExpansionHub[]) { +export async function list() { + const controlHub = await openConnectedControlHub(); + if (controlHub) { + console.log(`Control Hub: ${controlHub.moduleAddress}\n\n`); + } + + console.log("USB Expansion Hub:"); + const hubs: ExpansionHub[] = await openConnectedExpansionHubs(); for (const hub of hubs) { hub.on("error", (e: any) => { console.log(`Got error:`); @@ -9,10 +17,7 @@ export async function list(hubs: ExpansionHub[]) { }); console.log(hubHierarchyToString(hub)); } - - setTimeout(() => { - hubs.forEach(async (hub) => { - hub.close(); - }); - }, 2000); + hubs.forEach((hub) => { + hub.close(); + }); } From 8e68929d1ce09375ab6ca016ae56bf995edf57b5 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 25 May 2023 16:39:22 -0500 Subject: [PATCH 05/81] Check version of RC app --- package-lock.json | 52 +++++++++++-------- packages/control-hub/package.json | 4 +- .../control-hub/src/internal/ControlHub.ts | 9 ++-- packages/sample/src/command/list.ts | 1 + 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0091596d..5c5bfa60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,6 +3,7 @@ "lockfileVersion": 2, "requires": true, "packages": { + "packages": {}, "": { "name": "root", "workspaces": [ @@ -1954,11 +1955,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "node_modules/@types/ws": { "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -5137,11 +5143,6 @@ "node": ">=10" } }, - "node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" - }, "node_modules/node-fetch": { "version": "2.6.9", "dev": true, @@ -6640,7 +6641,6 @@ }, "node_modules/semver": { "version": "7.5.1", - "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" @@ -6654,7 +6654,6 @@ }, "node_modules/semver/node_modules/lru-cache": { "version": "6.0.0", - "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" @@ -7506,7 +7505,6 @@ }, "node_modules/yallist": { "version": "4.0.0", - "dev": true, "license": "ISC" }, "node_modules/yaml": { @@ -7549,10 +7547,12 @@ "@rev-robotics/rhsplib": "*", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", + "semver": "^7.5.1", "serialport": "^10.5.0" }, "devDependencies": { "@types/node": "^16.18.18", + "@types/semver": "^7.5.0", "typescript": "^5.0.2" } }, @@ -7594,6 +7594,11 @@ "typescript": "^5.0.2" } }, + "packages/rhsplib/node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "packages/sample": { "name": "rev-hub-cli", "version": "1.0.0", @@ -8869,8 +8874,10 @@ "requires": { "@rev-robotics/rhsplib": "*", "@types/node": "^16.18.18", + "@types/semver": "^7.5.0", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", + "semver": "^7.5.1", "serialport": "^10.5.0", "typescript": "^5.0.2" } @@ -8902,6 +8909,13 @@ "node-gyp-build": "^4.6.0", "prebuildify": "^5.0.1", "typescript": "^5.0.2" + }, + "dependencies": { + "node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + } } }, "@serialport/binding-mock": { @@ -8993,10 +9007,14 @@ "version": "4.0.0", "dev": true }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "dev": true + }, "@types/ws": { "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", - "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", "dev": true, "requires": { "@types/node": "*" @@ -11077,11 +11095,6 @@ "semver": "^7.3.5" } }, - "node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" - }, "node-fetch": { "version": "2.6.9", "dev": true, @@ -12043,14 +12056,12 @@ }, "semver": { "version": "7.5.1", - "dev": true, "requires": { "lru-cache": "^6.0.0" }, "dependencies": { "lru-cache": { "version": "6.0.0", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -12607,8 +12618,7 @@ "dev": true }, "yallist": { - "version": "4.0.0", - "dev": true + "version": "4.0.0" }, "yaml": { "version": "1.10.2", diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index fedd1e66..0a275526 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -6,11 +6,13 @@ "dependencies": { "serialport": "^10.5.0", "isomorphic-ws": "^5.0.0", - "axios":"^1.4.0", + "axios": "^1.4.0", + "semver": "^7.5.1", "@rev-robotics/rhsplib": "*" }, "devDependencies": { "@types/node": "^16.18.18", + "@types/semver": "^7.5.0", "typescript": "^5.0.2" }, "scripts": { diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 0da915ae..2f4c0365 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -16,6 +16,7 @@ import { Version, } from "@rev-robotics/rhsplib"; import axios from "axios"; +import semver from "semver"; import WebSocket from "isomorphic-ws"; export class ControlHub implements ExpansionHub { @@ -66,8 +67,8 @@ export class ControlHub implements ExpansionHub { timeout: 1000, }); if (response.data) { - return true; - //return response.data.webSocketApiVersion === "1"; + let rcVersion: string = response.data.rcVersion; + return semver.gt(rcVersion, semver.coerce("8.1")!.version); } return false; @@ -77,7 +78,9 @@ export class ControlHub implements ExpansionHub { } } - close(): void {} + close(): void { + this.webSocketConnection.close(); + } getADC(): Promise { return Promise.resolve(0); diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 24d96e5c..8bf7fd0b 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -6,6 +6,7 @@ export async function list() { const controlHub = await openConnectedControlHub(); if (controlHub) { console.log(`Control Hub: ${controlHub.moduleAddress}\n\n`); + controlHub.close(); } console.log("USB Expansion Hub:"); From fa7fbeabb35dcc7cb9a318f40c7b34f7721a0042 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 25 May 2023 16:39:43 -0500 Subject: [PATCH 06/81] Bump required RC version --- packages/control-hub/src/internal/ControlHub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 2f4c0365..dc244ba0 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -68,7 +68,7 @@ export class ControlHub implements ExpansionHub { }); if (response.data) { let rcVersion: string = response.data.rcVersion; - return semver.gt(rcVersion, semver.coerce("8.1")!.version); + return semver.gt(rcVersion, semver.coerce("8.2")!.version); } return false; From 035def24de052e872c41d65a7aa04004650f1173 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 25 May 2023 16:43:11 -0500 Subject: [PATCH 07/81] Change how semver requirement is declated --- packages/control-hub/src/internal/ControlHub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index dc244ba0..722349de 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -68,7 +68,7 @@ export class ControlHub implements ExpansionHub { }); if (response.data) { let rcVersion: string = response.data.rcVersion; - return semver.gt(rcVersion, semver.coerce("8.2")!.version); + return semver.satisfies(rcVersion, ">=8.2"); } return false; From 633c40c34df909c381a59128cf5ff814243390cc Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 25 May 2023 16:51:30 -0500 Subject: [PATCH 08/81] Remove error output if no WiFi hub connected --- packages/control-hub/src/discovery.ts | 28 ++++++++----------- .../control-hub/src/internal/ControlHub.ts | 1 - 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index 53ce4169..c04ec4a4 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -1,25 +1,21 @@ import { ControlHub } from "./internal/ControlHub"; -export async function openConnectedControlHub(): Promise< - ControlHub | undefined -> { - try { - return await createControlHub(); - } catch (e: any) { - console.log(e); - return undefined; - } +export async function openConnectedControlHub(): Promise { + try { + return await createControlHub(); + } catch (e: any) { + return undefined; + } } async function createControlHub(): Promise { - let hub = new ControlHub(); + let hub = new ControlHub(); - if(!await hub.isConnected()) { - console.log("Hub not connected") - throw new Error("Hub is not connected via WiFi"); - } + if (!(await hub.isConnected())) { + throw new Error("Hub is not connected via WiFi"); + } - await hub.open(); + await hub.open(); - return hub; + return hub; } diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 722349de..d218eb4a 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -73,7 +73,6 @@ export class ControlHub implements ExpansionHub { return false; } catch (e) { - console.log(e); return false; } } From e68ca9dbec2690e3af47ddb865f0b5fb52dd4c4b Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 26 May 2023 14:47:26 -0500 Subject: [PATCH 09/81] Detect USB control hubs --- package-lock.json | 499 +++++++++++++++++- packages/control-hub/package.json | 4 + packages/control-hub/src/discovery.ts | 75 ++- packages/control-hub/src/index.ts | 2 +- .../control-hub/src/internal/ControlHub.ts | 16 +- packages/expansion-hub/src/RevHubType.ts | 4 + packages/sample/package.json | 8 +- packages/sample/src/command/list.ts | 10 +- 8 files changed, 600 insertions(+), 18 deletions(-) create mode 100644 packages/expansion-hub/src/RevHubType.ts diff --git a/package-lock.json b/package-lock.json index 5c5bfa60..5bdefe54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,6 +103,12 @@ "node": ">=4" } }, + "node_modules/@devicefarmer/minicap-prebuilt": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@devicefarmer/minicap-prebuilt/-/minicap-prebuilt-2.7.1.tgz", + "integrity": "sha512-XM+mPIA9hgwSF4eOq0RnKSXycj2rLNm3Xsl7MM0kG3CtTpX3/J0AA8P+v8zWiGNCMxyhl2VwY52nmQE/QwN3zg==", + "optional": true + }, "node_modules/@gar/promisify": { "version": "1.1.3", "dev": true, @@ -1752,6 +1758,60 @@ "dev": true, "license": "MIT" }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "node_modules/@rev-robotics/control-hub": { "resolved": "packages/control-hub", "link": true @@ -1930,6 +1990,20 @@ "node": ">= 10" } }, + "node_modules/@types/debug": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "node_modules/@types/minimatch": { "version": "3.0.5", "dev": true, @@ -1940,11 +2014,25 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, "node_modules/@types/node": { "version": "16.18.25", - "dev": true, "license": "MIT" }, + "node_modules/@types/node-forge": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-TzX3ahoi9xbmaoT58smrBu7oa6dQXb/+PTNCslZyD/55tlJ/osofIMClzZsoo6buDFrg7e4DvVGkZqVgv6OLxw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "dev": true, @@ -1957,9 +2045,8 @@ }, "node_modules/@types/semver": { "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.5.5", @@ -1969,6 +2056,85 @@ "@types/node": "*" } }, + "node_modules/@u4/adbkit": { + "version": "4.1.19", + "resolved": "https://registry.npmjs.org/@u4/adbkit/-/adbkit-4.1.19.tgz", + "integrity": "sha512-NoPuiYKiv+wTS1qvfZ+GEJXUd4poxJQORLnncoPSi99+hxU0T/xSnv3V3MdFc45IS3IhSxN6eU0AVRP8xvgq+g==", + "dependencies": { + "@u4/adbkit-logcat": "2.1.2", + "@u4/adbkit-monkey": "^1.0.5", + "@u4/minicap-prebuilt": "^1.0.0", + "@xmldom/xmldom": "^0.8.7", + "commander": "9.4.1", + "debug": "~4.3.4", + "get-port": "5.1.1", + "node-forge": "^1.3.1", + "promise-duplex": "^6.0.0", + "promise-readable": "^6.0.0", + "protobufjs": "^6.11.3", + "xpath": "^0.0.32" + }, + "bin": { + "adbkit": "bin/adbkit" + }, + "engines": { + "node": ">= 12.20.0" + }, + "funding": { + "url": "https://github.com/sponsors/urielch" + }, + "optionalDependencies": { + "@devicefarmer/minicap-prebuilt": "^2.7.1" + } + }, + "node_modules/@u4/adbkit-logcat": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@u4/adbkit-logcat/-/adbkit-logcat-2.1.2.tgz", + "integrity": "sha512-mCAuqwWCA2MXYP8nfPJe9IJQ/aTkiFCVvF+qnsBXQ5ceaQOnw2JKNQxjz5Gw7dhYZ9iazvcxg6FNhyec5pfHeQ==", + "engines": { + "node": ">= 12.20.0" + } + }, + "node_modules/@u4/adbkit-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@u4/adbkit-monkey/-/adbkit-monkey-1.0.5.tgz", + "integrity": "sha512-6Hoz8EeKVK3eEJAGR44yzclADhA/5Q4KDlTtegMY4Dl5VMGq+tm1HtrmBvT++kftfrG64/H7xnrOwQ7DwQ2TlA==", + "engines": { + "node": ">= 12.20.0" + } + }, + "node_modules/@u4/adbkit/node_modules/commander": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/@u4/adbkit/node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@u4/minicap-prebuilt": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@u4/minicap-prebuilt/-/minicap-prebuilt-1.0.0.tgz", + "integrity": "sha512-z+hfnXEZmlCjNUfk4EioIWOLGoMg44a63FWcLqym2xSJuGP9WGS3qJ6ZXjT6ErYsuzSLPR0LGzCqfhXkQs/NBA==" + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.7.tgz", + "integrity": "sha512-sI1Ly2cODlWStkINzqGrZ8K6n+MTSbAeQnAipGyL+KZCXuHaRlj2gyyy8B/9MvsFFqN7XHryQnB2QwhzvJXovg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "dev": true, @@ -2737,6 +2903,16 @@ "node": ">=10" } }, + "node_modules/core-js": { + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", + "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "dev": true, @@ -3375,6 +3551,17 @@ "xtend": "~4.0.1" } }, + "node_modules/get-port": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-stream": { "version": "6.0.1", "dev": true, @@ -4645,6 +4832,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/lru-cache": { "version": "7.18.3", "dev": true, @@ -5162,6 +5354,14 @@ } } }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, "node_modules/node-gyp": { "version": "9.3.1", "dev": true, @@ -6168,11 +6368,35 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/promise-duplex": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-duplex/-/promise-duplex-6.0.0.tgz", + "integrity": "sha512-ZL7rquzjTFzInDBeWYcsT+qddolNvzigahk6MI6qLSbQvlyRRCJkU3JztgaVunzvkH28smRa2Qu/cY9RXtSkgA==", + "dependencies": { + "core-js": "^3.6.5", + "promise-readable": "^6.0.0", + "promise-writable": "^6.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/promise-inflight": { "version": "1.0.1", "dev": true, "license": "ISC" }, + "node_modules/promise-readable": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-readable/-/promise-readable-6.0.0.tgz", + "integrity": "sha512-5NxtmUswijvX5cAM0zPSy6yiCXH/eKBpiiBq6JfAUrmngMquMbzcBhF2qA+ocs4rYYKdvAfv3cOvZxADLtL1CA==", + "dependencies": { + "core-js": "^3.6.5" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/promise-retry": { "version": "2.0.1", "dev": true, @@ -6185,6 +6409,14 @@ "node": ">=10" } }, + "node_modules/promise-writable": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-writable/-/promise-writable-6.0.0.tgz", + "integrity": "sha512-b81zre/itgJFS7dwWzIdKNVVqvLiUxYRS/wolUB0H1YY/tAaS146XGKa4Q/5wCbsnXLyn0MCeV6f8HHe4iUHLg==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/promzard": { "version": "0.3.0", "dev": true, @@ -6198,6 +6430,31 @@ "dev": true, "license": "ISC" }, + "node_modules/protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/protocols": { "version": "2.0.1", "dev": true, @@ -7487,6 +7744,14 @@ } } }, + "node_modules/xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "dev": true, @@ -7554,6 +7819,10 @@ "@types/node": "^16.18.18", "@types/semver": "^7.5.0", "typescript": "^5.0.2" + }, + "peerDependencies": { + "@u4/adbkit": ">= 4.1.19", + "get-port": "^6.1.2" } }, "packages/core": { @@ -7604,13 +7873,17 @@ "version": "1.0.0", "dependencies": { "@rev-robotics/expansion-hub": "^1.0.0", + "@u4/adbkit": "^4.1.19", "commander": "^10.0.1", + "get-port": "^6.1.2", "ws": "8.13.0" }, "bin": { "rev-hub-cli": "revhub" }, "devDependencies": { + "@types/debug": "^4.1.8", + "@types/node-forge": "^1.3.2", "@types/ws": "^8.5.4" } } @@ -7676,6 +7949,12 @@ } } }, + "@devicefarmer/minicap-prebuilt": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@devicefarmer/minicap-prebuilt/-/minicap-prebuilt-2.7.1.tgz", + "integrity": "sha512-XM+mPIA9hgwSF4eOq0RnKSXycj2rLNm3Xsl7MM0kG3CtTpX3/J0AA8P+v8zWiGNCMxyhl2VwY52nmQE/QwN3zg==", + "optional": true + }, "@gar/promisify": { "version": "1.1.3", "dev": true @@ -8869,6 +9148,60 @@ } } }, + "@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + }, + "@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + }, + "@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + }, + "@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + }, + "@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "requires": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + }, + "@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + }, + "@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + }, + "@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + }, + "@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + }, "@rev-robotics/control-hub": { "version": "file:packages/control-hub", "requires": { @@ -8987,6 +9320,20 @@ "version": "2.0.0", "dev": true }, + "@types/debug": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, + "@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + }, "@types/minimatch": { "version": "3.0.5", "dev": true @@ -8995,10 +9342,24 @@ "version": "1.2.2", "dev": true }, - "@types/node": { - "version": "16.18.25", + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", "dev": true }, + "@types/node": { + "version": "16.18.25" + }, + "@types/node-forge": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-TzX3ahoi9xbmaoT58smrBu7oa6dQXb/+PTNCslZyD/55tlJ/osofIMClzZsoo6buDFrg7e4DvVGkZqVgv6OLxw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/normalize-package-data": { "version": "2.4.1", "dev": true @@ -9009,8 +9370,6 @@ }, "@types/semver": { "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, "@types/ws": { @@ -9020,6 +9379,58 @@ "@types/node": "*" } }, + "@u4/adbkit": { + "version": "4.1.19", + "resolved": "https://registry.npmjs.org/@u4/adbkit/-/adbkit-4.1.19.tgz", + "integrity": "sha512-NoPuiYKiv+wTS1qvfZ+GEJXUd4poxJQORLnncoPSi99+hxU0T/xSnv3V3MdFc45IS3IhSxN6eU0AVRP8xvgq+g==", + "requires": { + "@devicefarmer/minicap-prebuilt": "^2.7.1", + "@u4/adbkit-logcat": "2.1.2", + "@u4/adbkit-monkey": "^1.0.5", + "@u4/minicap-prebuilt": "^1.0.0", + "@xmldom/xmldom": "^0.8.7", + "commander": "9.4.1", + "debug": "~4.3.4", + "get-port": "5.1.1", + "node-forge": "^1.3.1", + "promise-duplex": "^6.0.0", + "promise-readable": "^6.0.0", + "protobufjs": "^6.11.3", + "xpath": "^0.0.32" + }, + "dependencies": { + "commander": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==" + }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" + } + } + }, + "@u4/adbkit-logcat": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@u4/adbkit-logcat/-/adbkit-logcat-2.1.2.tgz", + "integrity": "sha512-mCAuqwWCA2MXYP8nfPJe9IJQ/aTkiFCVvF+qnsBXQ5ceaQOnw2JKNQxjz5Gw7dhYZ9iazvcxg6FNhyec5pfHeQ==" + }, + "@u4/adbkit-monkey": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@u4/adbkit-monkey/-/adbkit-monkey-1.0.5.tgz", + "integrity": "sha512-6Hoz8EeKVK3eEJAGR44yzclADhA/5Q4KDlTtegMY4Dl5VMGq+tm1HtrmBvT++kftfrG64/H7xnrOwQ7DwQ2TlA==" + }, + "@u4/minicap-prebuilt": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@u4/minicap-prebuilt/-/minicap-prebuilt-1.0.0.tgz", + "integrity": "sha512-z+hfnXEZmlCjNUfk4EioIWOLGoMg44a63FWcLqym2xSJuGP9WGS3qJ6ZXjT6ErYsuzSLPR0LGzCqfhXkQs/NBA==" + }, + "@xmldom/xmldom": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.7.tgz", + "integrity": "sha512-sI1Ly2cODlWStkINzqGrZ8K6n+MTSbAeQnAipGyL+KZCXuHaRlj2gyyy8B/9MvsFFqN7XHryQnB2QwhzvJXovg==" + }, "@yarnpkg/lockfile": { "version": "1.1.0", "dev": true @@ -9526,6 +9937,11 @@ "q": "^1.5.1" } }, + "core-js": { + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", + "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==" + }, "core-util-is": { "version": "1.0.3", "dev": true @@ -9942,6 +10358,11 @@ } } }, + "get-port": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", + "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==" + }, "get-stream": { "version": "6.0.1", "dev": true @@ -10777,6 +11198,11 @@ "is-unicode-supported": "^0.1.0" } }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "lru-cache": { "version": "7.18.3", "dev": true @@ -11102,6 +11528,11 @@ "whatwg-url": "^5.0.0" } }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, "node-gyp": { "version": "9.3.1", "dev": true, @@ -11759,10 +12190,28 @@ "version": "1.0.2", "dev": true }, + "promise-duplex": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-duplex/-/promise-duplex-6.0.0.tgz", + "integrity": "sha512-ZL7rquzjTFzInDBeWYcsT+qddolNvzigahk6MI6qLSbQvlyRRCJkU3JztgaVunzvkH28smRa2Qu/cY9RXtSkgA==", + "requires": { + "core-js": "^3.6.5", + "promise-readable": "^6.0.0", + "promise-writable": "^6.0.0" + } + }, "promise-inflight": { "version": "1.0.1", "dev": true }, + "promise-readable": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-readable/-/promise-readable-6.0.0.tgz", + "integrity": "sha512-5NxtmUswijvX5cAM0zPSy6yiCXH/eKBpiiBq6JfAUrmngMquMbzcBhF2qA+ocs4rYYKdvAfv3cOvZxADLtL1CA==", + "requires": { + "core-js": "^3.6.5" + } + }, "promise-retry": { "version": "2.0.1", "dev": true, @@ -11771,6 +12220,11 @@ "retry": "^0.12.0" } }, + "promise-writable": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/promise-writable/-/promise-writable-6.0.0.tgz", + "integrity": "sha512-b81zre/itgJFS7dwWzIdKNVVqvLiUxYRS/wolUB0H1YY/tAaS146XGKa4Q/5wCbsnXLyn0MCeV6f8HHe4iUHLg==" + }, "promzard": { "version": "0.3.0", "dev": true, @@ -11782,6 +12236,26 @@ "version": "1.2.4", "dev": true }, + "protobufjs": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", + "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + } + }, "protocols": { "version": "2.0.1", "dev": true @@ -12002,8 +12476,12 @@ "version": "file:packages/sample", "requires": { "@rev-robotics/expansion-hub": "^1.0.0", + "@types/debug": "^4.1.8", + "@types/node-forge": "^1.3.2", "@types/ws": "^8.5.4", + "@u4/adbkit": "^4.1.19", "commander": "^10.0.1", + "get-port": "^6.1.2", "ws": "8.13.0" } }, @@ -12609,6 +13087,11 @@ "version": "8.13.0", "requires": {} }, + "xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" + }, "xtend": { "version": "4.0.2", "dev": true diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 0a275526..04e90127 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -10,6 +10,10 @@ "semver": "^7.5.1", "@rev-robotics/rhsplib": "*" }, + "peerDependencies": { + "@u4/adbkit": ">= 4.1.19", + "get-port": "^6.1.2" + }, "devDependencies": { "@types/node": "^16.18.18", "@types/semver": "^7.5.0", diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index c04ec4a4..97ad1876 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -1,17 +1,62 @@ -import { ControlHub } from "./internal/ControlHub"; +import { ControlHub } from "./internal/ControlHub.js"; +import { Adb, DeviceClient } from "@u4/adbkit"; +import getPort from "get-port"; export async function openConnectedControlHub(): Promise { try { - return await createControlHub(); + return await createWiFiControlHub(); } catch (e: any) { return undefined; } } -async function createControlHub(): Promise { +export async function openUsbControlHubs(): Promise { + let adbClient = Adb.createClient(); + + let devices = await adbClient.listDevices(); + let controlHubs = devices.filter(async (device) => { + let deviceClient = device.getClient(); + let isHub = await isControlHub(deviceClient); + console.log(`Is hub? ${isHub}`); + if (isHub) { + console.log("configuring tcp"); + await configureHubTcp(deviceClient); + } + return isHub; + }); + + console.log(`Found ${controlHubs.length} Control hubs`); + + let result: ControlHub[] = []; + + for (const device of controlHubs) { + let hub = new ControlHub(); + console.log("Opening hub"); + await hub.open(); + result.push(hub); + } + return result; +} + +async function configureHubTcp(deviceClient: DeviceClient) { + let port = await findAdjacentPorts(); + console.log(`Found port ${port}`); + await deviceClient.forward(`tcp:${port}`, `tcp:8080`); + await deviceClient.forward(`tcp:${port + 1}`, `tcp:8081`); +} + +async function isControlHub(deviceClient: DeviceClient): Promise { + let serialasusb = await deviceClient.execOut( + "getprop persist.ftcandroid.serialasusb", + "utf8", + ); + return serialasusb.startsWith("true"); +} + +async function createWiFiControlHub(): Promise { let hub = new ControlHub(); - if (!(await hub.isConnected())) { + if (!(await hub.isWiFiConnected())) { throw new Error("Hub is not connected via WiFi"); } @@ -19,3 +64,25 @@ async function createControlHub(): Promise { return hub; } + +/** + * Returns the first of two adjacent ports. + * @param host + */ +export async function findAdjacentPorts(host: string = "127.0.0.1"): Promise { + console.log("Finding ports"); + try { + //const getPort = (await import("get-port")).default; + let port = await getPort({ host: host }); + let adjacent = await getPort({ host: host, port: port + 1 }); + console.log("Tried to get ports"); + if (adjacent === port + 1) return port; + else { + return await findAdjacentPorts(host); + } + } catch (e) { + console.log("Got error checking ports"); + console.log(e); + throw e; + } +} diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index e5d405df..d66f791e 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,2 +1,2 @@ -export * from './discovery'; \ No newline at end of file +export { openConnectedControlHub, openUsbControlHubs } from "./discovery.js"; diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index d218eb4a..693ae790 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -18,6 +18,7 @@ import { import axios from "axios"; import semver from "semver"; import WebSocket from "isomorphic-ws"; +import adb from "@u4/adbkit"; export class ControlHub implements ExpansionHub { readonly isOpen: boolean = true; @@ -61,7 +62,7 @@ export class ControlHub implements ExpansionHub { }); } - async isConnected(): Promise { + async isWiFiConnected(): Promise { try { let response = await axios.get("http://192.168.43.1:8080/js/rcInfo.json", { timeout: 1000, @@ -77,6 +78,19 @@ export class ControlHub implements ExpansionHub { } } + async isUsbConnected(): Promise { + let adbClient = adb.createClient(); + let devices = await adbClient.listDevicesWithPaths(); + let controlHubs = devices.filter((device) => { + return this.isControlHub(device.path); + }); + return false; + } + + private isControlHub(path: string): boolean { + return path.includes("_box") && path.includes("msm8916_64"); + } + close(): void { this.webSocketConnection.close(); } diff --git a/packages/expansion-hub/src/RevHubType.ts b/packages/expansion-hub/src/RevHubType.ts new file mode 100644 index 00000000..de4220b4 --- /dev/null +++ b/packages/expansion-hub/src/RevHubType.ts @@ -0,0 +1,4 @@ +export enum RevHubType { + ExpansionHub, + ControlHub, +} diff --git a/packages/sample/package.json b/packages/sample/package.json index 07f075fb..0aee6602 100644 --- a/packages/sample/package.json +++ b/packages/sample/package.json @@ -9,10 +9,14 @@ "dependencies": { "@rev-robotics/expansion-hub": "^1.0.0", "ws": "8.13.0", - "commander": "^10.0.1" + "commander": "^10.0.1", + "@u4/adbkit": "^4.1.19", + "get-port": "^6.1.2" }, "devDependencies": { - "@types/ws": "^8.5.4" + "@types/ws": "^8.5.4", + "@types/node-forge": "^1.3.2", + "@types/debug": "^4.1.8" }, "scripts": { "build": "tsc", diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 8bf7fd0b..a735ec3c 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,11 +1,17 @@ import { hubHierarchyToString } from "../HubStringify.js"; -import { openConnectedControlHub } from "@rev-robotics/control-hub"; import {ExpansionHub} from "@rev-robotics/rev-hub-core"; +import { openConnectedControlHub, openUsbControlHubs } from "@rev-robotics/control-hub"; export async function list() { + let usbControlHubs = await openUsbControlHubs(); + for (const hub of usbControlHubs) { + console.log(`USB Control Hub: ${hub.moduleAddress}\n\n`); + hub.close(); + } + const controlHub = await openConnectedControlHub(); if (controlHub) { - console.log(`Control Hub: ${controlHub.moduleAddress}\n\n`); + console.log(`WiFi Control Hub: ${controlHub.moduleAddress}\n\n`); controlHub.close(); } From 68ab5e0a1e4a5882e8963f24a5fd463b5c7ad06a Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 26 May 2023 16:55:21 -0500 Subject: [PATCH 10/81] Fix connection to USB expansion hubs --- packages/control-hub/src/discovery.ts | 33 +++++++------------ .../control-hub/src/internal/ControlHub.ts | 13 ++------ packages/sample/src/HubStringify.ts | 2 +- packages/sample/src/command/list.ts | 1 - 4 files changed, 15 insertions(+), 34 deletions(-) diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index 97ad1876..788f0b9d 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -12,37 +12,30 @@ export async function openConnectedControlHub(): Promise export async function openUsbControlHubs(): Promise { let adbClient = Adb.createClient(); + let controlHubs: ControlHub[] = []; let devices = await adbClient.listDevices(); - let controlHubs = devices.filter(async (device) => { + for (const device of devices) { let deviceClient = device.getClient(); let isHub = await isControlHub(deviceClient); - console.log(`Is hub? ${isHub}`); if (isHub) { - console.log("configuring tcp"); - await configureHubTcp(deviceClient); - } - return isHub; - }); - - console.log(`Found ${controlHubs.length} Control hubs`); - - let result: ControlHub[] = []; + let port = await configureHubTcp(deviceClient); - for (const device of controlHubs) { - let hub = new ControlHub(); - console.log("Opening hub"); - await hub.open(); - result.push(hub); + let hub = new ControlHub(); + await hub.open("127.0.0.1", (port + 1).toString()); + controlHubs.push(hub); + } } - return result; + + return controlHubs; } -async function configureHubTcp(deviceClient: DeviceClient) { +async function configureHubTcp(deviceClient: DeviceClient): Promise { let port = await findAdjacentPorts(); - console.log(`Found port ${port}`); await deviceClient.forward(`tcp:${port}`, `tcp:8080`); await deviceClient.forward(`tcp:${port + 1}`, `tcp:8081`); + + return port; } async function isControlHub(deviceClient: DeviceClient): Promise { @@ -70,12 +63,10 @@ async function createWiFiControlHub(): Promise { * @param host */ export async function findAdjacentPorts(host: string = "127.0.0.1"): Promise { - console.log("Finding ports"); try { //const getPort = (await import("get-port")).default; let port = await getPort({ host: host }); let adjacent = await getPort({ host: host, port: port + 1 }); - console.log("Tried to get ports"); if (adjacent === port + 1) return port; else { return await findAdjacentPorts(host); diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 693ae790..1801124e 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -33,8 +33,8 @@ export class ControlHub implements ExpansionHub { (response: any | undefined, error: any | undefined) => void >(); - async open(): Promise { - this.webSocketConnection = new WebSocket("ws://192.168.43.1:8081"); + async open(ip: string = "192.168.43.1", port: string = "8081"): Promise { + this.webSocketConnection = new WebSocket(`ws://${ip}:${port}`); this.webSocketConnection.on("message", (data) => { let rawMessage = JSON.parse(data.toString()); @@ -78,15 +78,6 @@ export class ControlHub implements ExpansionHub { } } - async isUsbConnected(): Promise { - let adbClient = adb.createClient(); - let devices = await adbClient.listDevicesWithPaths(); - let controlHubs = devices.filter((device) => { - return this.isControlHub(device.path); - }); - return false; - } - private isControlHub(path: string): boolean { return path.includes("_box") && path.includes("msm8916_64"); } diff --git a/packages/sample/src/HubStringify.ts b/packages/sample/src/HubStringify.ts index b607320a..91431d19 100644 --- a/packages/sample/src/HubStringify.ts +++ b/packages/sample/src/HubStringify.ts @@ -9,7 +9,7 @@ export function hubHierarchyToString(hub: RevHub): string { if (hub.isParent()) { for (const child of hub.children) { - result += `\tRevHub: ${child.moduleAddress}\n`; + result += `\tUSB Expansion Hub: ${child.moduleAddress}\n`; } } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index a735ec3c..7263bd52 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -15,7 +15,6 @@ export async function list() { controlHub.close(); } - console.log("USB Expansion Hub:"); const hubs: ExpansionHub[] = await openConnectedExpansionHubs(); for (const hub of hubs) { hub.on("error", (e: any) => { From 167d412fe230211952dbcc1dfa7859541468e151 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 09:26:37 -0500 Subject: [PATCH 11/81] Add explicit dependency on control-hub --- package-lock.json | 1 + .../control-hub/src/internal/ControlHub.ts | 26 +++++++++---------- packages/expansion-hub/src/index.ts | 4 +++ packages/sample/package.json | 1 + 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5bdefe54..dd66511b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7873,6 +7873,7 @@ "version": "1.0.0", "dependencies": { "@rev-robotics/expansion-hub": "^1.0.0", + "@rev-robotics/control-hub": "^0.1.0", "@u4/adbkit": "^4.1.19", "commander": "^10.0.1", "get-port": "^6.1.2", diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 1801124e..348c6ac8 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -1,24 +1,22 @@ -import { ExpansionHub, ParentRevHub, RevHub } from "@rev-robotics/expansion-hub"; -import { RevHubType } from "@rev-robotics/expansion-hub/dist/RevHubType"; +import { ExpansionHub, ParentRevHub, RevHub, RevHubType } from "@rev-robotics/expansion-hub"; import { BulkInputData, DebugGroup, - DIODirection, + DioDirection, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, - LEDPattern, + LedPattern, ModuleInterface, ModuleStatus, - PIDCoefficients, - RGB, + PidCoefficients, + Rgb, VerbosityLevel, Version, } from "@rev-robotics/rhsplib"; import axios from "axios"; import semver from "semver"; import WebSocket from "isomorphic-ws"; -import adb from "@u4/adbkit"; export class ControlHub implements ExpansionHub { readonly isOpen: boolean = true; @@ -98,7 +96,7 @@ export class ControlHub implements ExpansionHub { throw new Error("not implemented"); } - async getDigitalDirection(dioPin: number): Promise { + async getDigitalDirection(dioPin: number): Promise { throw new Error("not implemented"); } @@ -126,11 +124,11 @@ export class ControlHub implements ExpansionHub { return Promise.resolve(0); } - getModuleLedColor(): Promise { + getModuleLedColor(): Promise { throw new Error("not implemented"); } - getModuleLedPattern(): Promise { + getModuleLedPattern(): Promise { throw new Error("not implemented"); } @@ -167,7 +165,7 @@ export class ControlHub implements ExpansionHub { getMotorPIDCoefficients( motorChannel: number, motorMode: number, - ): Promise { + ): Promise { throw new Error("not implemented"); } @@ -268,7 +266,7 @@ export class ControlHub implements ExpansionHub { throw new Error("not implemented"); } - setDigitalDirection(dioPin: number, direction: DIODirection): Promise { + setDigitalDirection(dioPin: number, direction: DioDirection): Promise { throw new Error("not implemented"); } @@ -291,7 +289,7 @@ export class ControlHub implements ExpansionHub { throw new Error("not implemented"); } - setModuleLedPattern(ledPattern: LEDPattern): Promise { + setModuleLedPattern(ledPattern: LedPattern): Promise { throw new Error("not implemented"); } @@ -321,7 +319,7 @@ export class ControlHub implements ExpansionHub { setMotorPIDCoefficients( motorChannel: number, motorMode: number, - pid: PIDCoefficients, + pid: PidCoefficients, ): Promise { throw new Error("not implemented"); } diff --git a/packages/expansion-hub/src/index.ts b/packages/expansion-hub/src/index.ts index 5e72861d..12bab18c 100644 --- a/packages/expansion-hub/src/index.ts +++ b/packages/expansion-hub/src/index.ts @@ -47,4 +47,8 @@ export { BatteryTooLowToRunServoError, TimeoutError, UnrecognizedNackError, + RevHubType, + RevHub, + ParentRevHub, + ExpansionHub, } from "@rev-robotics/rev-hub-core"; diff --git a/packages/sample/package.json b/packages/sample/package.json index 0aee6602..35586ef6 100644 --- a/packages/sample/package.json +++ b/packages/sample/package.json @@ -8,6 +8,7 @@ "type": "module", "dependencies": { "@rev-robotics/expansion-hub": "^1.0.0", + "@rev-robotics/control-hub": "^0.1.0", "ws": "8.13.0", "commander": "^10.0.1", "@u4/adbkit": "^4.1.19", From c28c954d4319640ccd4ce04cca3ab965b7008c1b Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 09:49:01 -0500 Subject: [PATCH 12/81] Restructure Control Hub module to export interface and implement with internal class --- packages/control-hub/src/ControlHub.ts | 7 +++++++ packages/control-hub/src/discovery.ts | 8 +++++--- packages/control-hub/src/index.ts | 1 + packages/control-hub/src/internal/ControlHub.ts | 16 +++++++++++----- packages/sample/src/command/list.ts | 6 +++++- 5 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 packages/control-hub/src/ControlHub.ts diff --git a/packages/control-hub/src/ControlHub.ts b/packages/control-hub/src/ControlHub.ts new file mode 100644 index 00000000..01e28c1e --- /dev/null +++ b/packages/control-hub/src/ControlHub.ts @@ -0,0 +1,7 @@ +import { ExpansionHub, ParentRevHub } from "@rev-robotics/expansion-hub"; + +export interface ParentControlHub extends ParentRevHub, ControlHub { + readonly serialNumber: string; +} + +export interface ControlHub extends ExpansionHub {} diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index 788f0b9d..4da839de 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -1,6 +1,7 @@ -import { ControlHub } from "./internal/ControlHub.js"; +import { ControlHubInternal } from "./internal/ControlHub.js"; import { Adb, DeviceClient } from "@u4/adbkit"; import getPort from "get-port"; +import { ControlHub } from "./ControlHub.js"; export async function openConnectedControlHub(): Promise { try { @@ -20,8 +21,9 @@ export async function openUsbControlHubs(): Promise { let isHub = await isControlHub(deviceClient); if (isHub) { let port = await configureHubTcp(deviceClient); + let serialNumber = device.id; - let hub = new ControlHub(); + let hub = new ControlHubInternal(serialNumber); await hub.open("127.0.0.1", (port + 1).toString()); controlHubs.push(hub); } @@ -47,7 +49,7 @@ async function isControlHub(deviceClient: DeviceClient): Promise { } async function createWiFiControlHub(): Promise { - let hub = new ControlHub(); + let hub = new ControlHubInternal(); if (!(await hub.isWiFiConnected())) { throw new Error("Hub is not connected via WiFi"); diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index d66f791e..fdedcab7 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,2 +1,3 @@ export { openConnectedControlHub, openUsbControlHubs } from "./discovery.js"; +export * from "./ControlHub.js"; diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 348c6ac8..1e689580 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -17,13 +17,15 @@ import { import axios from "axios"; import semver from "semver"; import WebSocket from "isomorphic-ws"; +import { ControlHub, ParentControlHub } from "../ControlHub.js"; -export class ControlHub implements ExpansionHub { +export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; moduleAddress: number = 0; responseTimeoutMs: number = 0; type: RevHubType = RevHubType.ControlHub; webSocketConnection!: WebSocket; + private readonly serialNumber?: string; keyGenerator = 0; currentActiveCommands = new Map< @@ -31,6 +33,14 @@ export class ControlHub implements ExpansionHub { (response: any | undefined, error: any | undefined) => void >(); + constructor(serialNumber?: string) { + this.serialNumber = serialNumber; + } + + isParent(): this is ParentControlHub { + return this.serialNumber !== undefined; + } + async open(ip: string = "192.168.43.1", port: string = "8081"): Promise { this.webSocketConnection = new WebSocket(`ws://${ip}:${port}`); @@ -203,10 +213,6 @@ export class ControlHub implements ExpansionHub { throw new Error("not implemented"); } - isParent(): this is ParentRevHub { - throw new Error("not implemented"); - } - on(eventName: "error", listener: (error: Error) => void): RevHub { throw new Error("not implemented"); } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 7263bd52..c5aa9e31 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -5,7 +5,11 @@ import { openConnectedControlHub, openUsbControlHubs } from "@rev-robotics/contr export async function list() { let usbControlHubs = await openUsbControlHubs(); for (const hub of usbControlHubs) { - console.log(`USB Control Hub: ${hub.moduleAddress}\n\n`); + if (hub.isParent()) { + console.log(`USB Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n\n`); + } else { + console.log(`\tUSB Control Hub: ${hub.moduleAddress}\n\n`); + } hub.close(); } From c97514080eee83f1b779fa2cda4db9f26c99fa78 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 09:50:45 -0500 Subject: [PATCH 13/81] Show serial number for parent expansion hub --- packages/sample/src/HubStringify.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sample/src/HubStringify.ts b/packages/sample/src/HubStringify.ts index 91431d19..95d63f84 100644 --- a/packages/sample/src/HubStringify.ts +++ b/packages/sample/src/HubStringify.ts @@ -8,6 +8,7 @@ export function hubHierarchyToString(hub: RevHub): string { let result = `RevHub ${serialNumberText}: ${hub.moduleAddress}\n`; if (hub.isParent()) { + result = `USB Expansion Hub: ${hub.serialNumber} ${hub.moduleAddress}\n`; for (const child of hub.children) { result += `\tUSB Expansion Hub: ${child.moduleAddress}\n`; } From 1a7f6e1bb70f76792a2cd2418fbc108b5b6a9608 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 13:07:46 -0500 Subject: [PATCH 14/81] Remove ParentControlHub, since control hubs will always be parents --- package-lock.json | 1 + packages/control-hub/package.json | 1 + packages/control-hub/src/ControlHub.ts | 6 +----- packages/control-hub/src/discovery.ts | 2 +- packages/control-hub/src/internal/ControlHub.ts | 15 ++++++++++++--- packages/sample/src/command/list.ts | 6 +----- 6 files changed, 17 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd66511b..374b09fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7817,6 +7817,7 @@ }, "devDependencies": { "@types/node": "^16.18.18", + "@types/node-forge": "^1.3.2", "@types/semver": "^7.5.0", "typescript": "^5.0.2" }, diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 04e90127..c891bbf8 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -17,6 +17,7 @@ "devDependencies": { "@types/node": "^16.18.18", "@types/semver": "^7.5.0", + "@types/node-forge": "^1.3.2", "typescript": "^5.0.2" }, "scripts": { diff --git a/packages/control-hub/src/ControlHub.ts b/packages/control-hub/src/ControlHub.ts index 01e28c1e..07582e58 100644 --- a/packages/control-hub/src/ControlHub.ts +++ b/packages/control-hub/src/ControlHub.ts @@ -1,7 +1,3 @@ import { ExpansionHub, ParentRevHub } from "@rev-robotics/expansion-hub"; -export interface ParentControlHub extends ParentRevHub, ControlHub { - readonly serialNumber: string; -} - -export interface ControlHub extends ExpansionHub {} +export interface ControlHub extends ExpansionHub, ParentRevHub {} diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index 4da839de..49ba71e6 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -49,7 +49,7 @@ async function isControlHub(deviceClient: DeviceClient): Promise { } async function createWiFiControlHub(): Promise { - let hub = new ControlHubInternal(); + let hub = new ControlHubInternal("Placeholder"); if (!(await hub.isWiFiConnected())) { throw new Error("Hub is not connected via WiFi"); diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 1e689580..ec7756b7 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -25,7 +25,8 @@ export class ControlHubInternal implements ControlHub { responseTimeoutMs: number = 0; type: RevHubType = RevHubType.ControlHub; webSocketConnection!: WebSocket; - private readonly serialNumber?: string; + readonly serialNumber: string; + readonly children: ReadonlyArray = []; keyGenerator = 0; currentActiveCommands = new Map< @@ -33,11 +34,11 @@ export class ControlHubInternal implements ControlHub { (response: any | undefined, error: any | undefined) => void >(); - constructor(serialNumber?: string) { + constructor(serialNumber: string) { this.serialNumber = serialNumber; } - isParent(): this is ParentControlHub { + isParent(): this is ParentRevHub { return this.serialNumber !== undefined; } @@ -412,4 +413,12 @@ export class ControlHubInternal implements ControlHub { }); }); } + + addChild(hub: RevHub): void { + throw new Error("not implemented"); + } + + addChildByAddress(moduleAddress: number): Promise { + throw new Error("not implemented"); + } } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index c5aa9e31..2d6ab3c3 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -5,11 +5,7 @@ import { openConnectedControlHub, openUsbControlHubs } from "@rev-robotics/contr export async function list() { let usbControlHubs = await openUsbControlHubs(); for (const hub of usbControlHubs) { - if (hub.isParent()) { - console.log(`USB Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n\n`); - } else { - console.log(`\tUSB Control Hub: ${hub.moduleAddress}\n\n`); - } + console.log(`USB Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n\n`); hub.close(); } From d8516942226c02e70c68f8e4c4e164cc00df3522 Mon Sep 17 00:00:00 2001 From: Landry Norris <37489471+LandryNorris@users.noreply.github.com> Date: Tue, 30 May 2023 13:17:14 -0500 Subject: [PATCH 15/81] Fix wording in package description Co-authored-by: Noah Andrews --- packages/control-hub/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index c891bbf8..366a4910 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -1,7 +1,7 @@ { "name": "@rev-robotics/control-hub", "version": "0.1.0", - "description": "High level library for REV control hub", + "description": "High level library for the REV Robotics Control Hub", "main": "dist/index.js", "dependencies": { "serialport": "^10.5.0", From d17e60bb75046dcee0d0e86fdd3dcc5919f4fcb2 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 14:18:08 -0500 Subject: [PATCH 16/81] Create core module --- package-lock.json | 207 +++++------------- packages/control-hub/package.json | 3 +- packages/control-hub/src/ControlHub.ts | 3 - packages/control-hub/src/discovery.ts | 2 +- packages/control-hub/src/index.ts | 1 - .../control-hub/src/internal/ControlHub.ts | 15 +- packages/core/src/ControlHub.ts | 4 + packages/core/src/ExpansionHub.ts | 36 +-- packages/core/src/RevHub.ts | 2 +- packages/core/tsconfig.json | 4 +- packages/expansion-hub/src/RevHubType.ts | 4 - .../src/internal/ExpansionHub.ts | 31 +-- packages/expansion-hub/src/open-rev-hub.ts | 1 - packages/sample/src/command/led.ts | 4 +- packages/sample/src/command/list.ts | 3 +- 15 files changed, 114 insertions(+), 206 deletions(-) delete mode 100644 packages/control-hub/src/ControlHub.ts create mode 100644 packages/core/src/ControlHub.ts delete mode 100644 packages/expansion-hub/src/RevHubType.ts diff --git a/package-lock.json b/package-lock.json index 374b09fb..ce32c306 100644 --- a/package-lock.json +++ b/package-lock.json @@ -105,8 +105,7 @@ }, "node_modules/@devicefarmer/minicap-prebuilt": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@devicefarmer/minicap-prebuilt/-/minicap-prebuilt-2.7.1.tgz", - "integrity": "sha512-XM+mPIA9hgwSF4eOq0RnKSXycj2rLNm3Xsl7MM0kG3CtTpX3/J0AA8P+v8zWiGNCMxyhl2VwY52nmQE/QwN3zg==", + "license": "Apache-2.0", "optional": true }, "node_modules/@gar/promisify": { @@ -1760,28 +1759,23 @@ }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -1789,28 +1783,23 @@ }, "node_modules/@protobufjs/float": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "license": "BSD-3-Clause" }, "node_modules/@rev-robotics/control-hub": { "resolved": "packages/control-hub", @@ -1992,17 +1981,15 @@ }, "node_modules/@types/debug": { "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/long": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + "license": "MIT" }, "node_modules/@types/minimatch": { "version": "3.0.5", @@ -2016,9 +2003,8 @@ }, "node_modules/@types/ms": { "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "16.18.25", @@ -2026,9 +2012,8 @@ }, "node_modules/@types/node-forge": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-TzX3ahoi9xbmaoT58smrBu7oa6dQXb/+PTNCslZyD/55tlJ/osofIMClzZsoo6buDFrg7e4DvVGkZqVgv6OLxw==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -2058,8 +2043,7 @@ }, "node_modules/@u4/adbkit": { "version": "4.1.19", - "resolved": "https://registry.npmjs.org/@u4/adbkit/-/adbkit-4.1.19.tgz", - "integrity": "sha512-NoPuiYKiv+wTS1qvfZ+GEJXUd4poxJQORLnncoPSi99+hxU0T/xSnv3V3MdFc45IS3IhSxN6eU0AVRP8xvgq+g==", + "license": "Apache-2.0", "dependencies": { "@u4/adbkit-logcat": "2.1.2", "@u4/adbkit-monkey": "^1.0.5", @@ -2089,32 +2073,28 @@ }, "node_modules/@u4/adbkit-logcat": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@u4/adbkit-logcat/-/adbkit-logcat-2.1.2.tgz", - "integrity": "sha512-mCAuqwWCA2MXYP8nfPJe9IJQ/aTkiFCVvF+qnsBXQ5ceaQOnw2JKNQxjz5Gw7dhYZ9iazvcxg6FNhyec5pfHeQ==", + "license": "Apache-2.0", "engines": { "node": ">= 12.20.0" } }, "node_modules/@u4/adbkit-monkey": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@u4/adbkit-monkey/-/adbkit-monkey-1.0.5.tgz", - "integrity": "sha512-6Hoz8EeKVK3eEJAGR44yzclADhA/5Q4KDlTtegMY4Dl5VMGq+tm1HtrmBvT++kftfrG64/H7xnrOwQ7DwQ2TlA==", + "license": "Apache-2.0", "engines": { "node": ">= 12.20.0" } }, "node_modules/@u4/adbkit/node_modules/commander": { "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "license": "MIT", "engines": { "node": "^12.20.0 || >=14" } }, "node_modules/@u4/adbkit/node_modules/get-port": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "license": "MIT", "engines": { "node": ">=8" }, @@ -2124,13 +2104,11 @@ }, "node_modules/@u4/minicap-prebuilt": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@u4/minicap-prebuilt/-/minicap-prebuilt-1.0.0.tgz", - "integrity": "sha512-z+hfnXEZmlCjNUfk4EioIWOLGoMg44a63FWcLqym2xSJuGP9WGS3qJ6ZXjT6ErYsuzSLPR0LGzCqfhXkQs/NBA==" + "license": "Apache-2.0" }, "node_modules/@xmldom/xmldom": { "version": "0.8.7", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.7.tgz", - "integrity": "sha512-sI1Ly2cODlWStkINzqGrZ8K6n+MTSbAeQnAipGyL+KZCXuHaRlj2gyyy8B/9MvsFFqN7XHryQnB2QwhzvJXovg==", + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -2905,9 +2883,8 @@ }, "node_modules/core-js": { "version": "3.30.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", - "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==", "hasInstallScript": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" @@ -3553,8 +3530,7 @@ }, "node_modules/get-port": { "version": "6.1.2", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", - "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==", + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -4834,8 +4810,7 @@ }, "node_modules/long": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "license": "Apache-2.0" }, "node_modules/lru-cache": { "version": "7.18.3", @@ -5356,8 +5331,7 @@ }, "node_modules/node-forge": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" } @@ -6370,8 +6344,7 @@ }, "node_modules/promise-duplex": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-duplex/-/promise-duplex-6.0.0.tgz", - "integrity": "sha512-ZL7rquzjTFzInDBeWYcsT+qddolNvzigahk6MI6qLSbQvlyRRCJkU3JztgaVunzvkH28smRa2Qu/cY9RXtSkgA==", + "license": "MIT", "dependencies": { "core-js": "^3.6.5", "promise-readable": "^6.0.0", @@ -6388,8 +6361,7 @@ }, "node_modules/promise-readable": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-readable/-/promise-readable-6.0.0.tgz", - "integrity": "sha512-5NxtmUswijvX5cAM0zPSy6yiCXH/eKBpiiBq6JfAUrmngMquMbzcBhF2qA+ocs4rYYKdvAfv3cOvZxADLtL1CA==", + "license": "MIT", "dependencies": { "core-js": "^3.6.5" }, @@ -6411,8 +6383,7 @@ }, "node_modules/promise-writable": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-writable/-/promise-writable-6.0.0.tgz", - "integrity": "sha512-b81zre/itgJFS7dwWzIdKNVVqvLiUxYRS/wolUB0H1YY/tAaS146XGKa4Q/5wCbsnXLyn0MCeV6f8HHe4iUHLg==", + "license": "MIT", "engines": { "node": ">=10.0.0" } @@ -6432,9 +6403,8 @@ }, "node_modules/protobufjs": { "version": "6.11.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", - "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -7746,8 +7716,7 @@ }, "node_modules/xpath": { "version": "0.0.32", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", - "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", + "license": "MIT", "engines": { "node": ">=0.6.0" } @@ -7809,6 +7778,7 @@ "name": "@rev-robotics/control-hub", "version": "0.1.0", "dependencies": { + "@rev-robotics/rev-hub-core": "*", "@rev-robotics/rhsplib": "*", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", @@ -7873,8 +7843,8 @@ "name": "rev-hub-cli", "version": "1.0.0", "dependencies": { - "@rev-robotics/expansion-hub": "^1.0.0", "@rev-robotics/control-hub": "^0.1.0", + "@rev-robotics/expansion-hub": "^1.0.0", "@u4/adbkit": "^4.1.19", "commander": "^10.0.1", "get-port": "^6.1.2", @@ -7953,8 +7923,6 @@ }, "@devicefarmer/minicap-prebuilt": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@devicefarmer/minicap-prebuilt/-/minicap-prebuilt-2.7.1.tgz", - "integrity": "sha512-XM+mPIA9hgwSF4eOq0RnKSXycj2rLNm3Xsl7MM0kG3CtTpX3/J0AA8P+v8zWiGNCMxyhl2VwY52nmQE/QwN3zg==", "optional": true }, "@gar/promisify": { @@ -9151,64 +9119,46 @@ } }, "@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "version": "1.1.2" }, "@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "version": "1.1.2" }, "@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "version": "2.0.4" }, "@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "version": "1.1.0" }, "@protobufjs/fetch": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "version": "1.0.2" }, "@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "version": "1.1.0" }, "@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "version": "1.1.2" }, "@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "version": "1.1.0" }, "@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "version": "1.1.0" }, "@rev-robotics/control-hub": { "version": "file:packages/control-hub", "requires": { + "@rev-robotics/rev-hub-core": "*", "@rev-robotics/rhsplib": "*", "@types/node": "^16.18.18", + "@types/node-forge": "^1.3.2", "@types/semver": "^7.5.0", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", @@ -9324,17 +9274,13 @@ }, "@types/debug": { "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", "dev": true, "requires": { "@types/ms": "*" } }, "@types/long": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + "version": "4.0.2" }, "@types/minimatch": { "version": "3.0.5", @@ -9346,8 +9292,6 @@ }, "@types/ms": { "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", "dev": true }, "@types/node": { @@ -9355,8 +9299,6 @@ }, "@types/node-forge": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-TzX3ahoi9xbmaoT58smrBu7oa6dQXb/+PTNCslZyD/55tlJ/osofIMClzZsoo6buDFrg7e4DvVGkZqVgv6OLxw==", "dev": true, "requires": { "@types/node": "*" @@ -9383,8 +9325,6 @@ }, "@u4/adbkit": { "version": "4.1.19", - "resolved": "https://registry.npmjs.org/@u4/adbkit/-/adbkit-4.1.19.tgz", - "integrity": "sha512-NoPuiYKiv+wTS1qvfZ+GEJXUd4poxJQORLnncoPSi99+hxU0T/xSnv3V3MdFc45IS3IhSxN6eU0AVRP8xvgq+g==", "requires": { "@devicefarmer/minicap-prebuilt": "^2.7.1", "@u4/adbkit-logcat": "2.1.2", @@ -9402,36 +9342,24 @@ }, "dependencies": { "commander": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", - "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==" + "version": "9.4.1" }, "get-port": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" + "version": "5.1.1" } } }, "@u4/adbkit-logcat": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@u4/adbkit-logcat/-/adbkit-logcat-2.1.2.tgz", - "integrity": "sha512-mCAuqwWCA2MXYP8nfPJe9IJQ/aTkiFCVvF+qnsBXQ5ceaQOnw2JKNQxjz5Gw7dhYZ9iazvcxg6FNhyec5pfHeQ==" + "version": "2.1.2" }, "@u4/adbkit-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@u4/adbkit-monkey/-/adbkit-monkey-1.0.5.tgz", - "integrity": "sha512-6Hoz8EeKVK3eEJAGR44yzclADhA/5Q4KDlTtegMY4Dl5VMGq+tm1HtrmBvT++kftfrG64/H7xnrOwQ7DwQ2TlA==" + "version": "1.0.5" }, "@u4/minicap-prebuilt": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@u4/minicap-prebuilt/-/minicap-prebuilt-1.0.0.tgz", - "integrity": "sha512-z+hfnXEZmlCjNUfk4EioIWOLGoMg44a63FWcLqym2xSJuGP9WGS3qJ6ZXjT6ErYsuzSLPR0LGzCqfhXkQs/NBA==" + "version": "1.0.0" }, "@xmldom/xmldom": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.7.tgz", - "integrity": "sha512-sI1Ly2cODlWStkINzqGrZ8K6n+MTSbAeQnAipGyL+KZCXuHaRlj2gyyy8B/9MvsFFqN7XHryQnB2QwhzvJXovg==" + "version": "0.8.7" }, "@yarnpkg/lockfile": { "version": "1.1.0", @@ -9940,9 +9868,7 @@ } }, "core-js": { - "version": "3.30.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", - "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==" + "version": "3.30.2" }, "core-util-is": { "version": "1.0.3", @@ -10361,9 +10287,7 @@ } }, "get-port": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-6.1.2.tgz", - "integrity": "sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==" + "version": "6.1.2" }, "get-stream": { "version": "6.0.1", @@ -11201,9 +11125,7 @@ } }, "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "version": "4.0.0" }, "lru-cache": { "version": "7.18.3", @@ -11531,9 +11453,7 @@ } }, "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + "version": "1.3.1" }, "node-gyp": { "version": "9.3.1", @@ -12194,8 +12114,6 @@ }, "promise-duplex": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-duplex/-/promise-duplex-6.0.0.tgz", - "integrity": "sha512-ZL7rquzjTFzInDBeWYcsT+qddolNvzigahk6MI6qLSbQvlyRRCJkU3JztgaVunzvkH28smRa2Qu/cY9RXtSkgA==", "requires": { "core-js": "^3.6.5", "promise-readable": "^6.0.0", @@ -12208,8 +12126,6 @@ }, "promise-readable": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-readable/-/promise-readable-6.0.0.tgz", - "integrity": "sha512-5NxtmUswijvX5cAM0zPSy6yiCXH/eKBpiiBq6JfAUrmngMquMbzcBhF2qA+ocs4rYYKdvAfv3cOvZxADLtL1CA==", "requires": { "core-js": "^3.6.5" } @@ -12223,9 +12139,7 @@ } }, "promise-writable": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/promise-writable/-/promise-writable-6.0.0.tgz", - "integrity": "sha512-b81zre/itgJFS7dwWzIdKNVVqvLiUxYRS/wolUB0H1YY/tAaS146XGKa4Q/5wCbsnXLyn0MCeV6f8HHe4iUHLg==" + "version": "6.0.0" }, "promzard": { "version": "0.3.0", @@ -12240,8 +12154,6 @@ }, "protobufjs": { "version": "6.11.3", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.3.tgz", - "integrity": "sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -12477,6 +12389,7 @@ "rev-hub-cli": { "version": "file:packages/sample", "requires": { + "@rev-robotics/control-hub": "^0.1.0", "@rev-robotics/expansion-hub": "^1.0.0", "@types/debug": "^4.1.8", "@types/node-forge": "^1.3.2", @@ -13090,9 +13003,7 @@ "requires": {} }, "xpath": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", - "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" + "version": "0.0.32" }, "xtend": { "version": "4.0.2", diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 366a4910..feac0164 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -8,7 +8,8 @@ "isomorphic-ws": "^5.0.0", "axios": "^1.4.0", "semver": "^7.5.1", - "@rev-robotics/rhsplib": "*" + "@rev-robotics/rhsplib": "*", + "@rev-robotics/rev-hub-core": "*" }, "peerDependencies": { "@u4/adbkit": ">= 4.1.19", diff --git a/packages/control-hub/src/ControlHub.ts b/packages/control-hub/src/ControlHub.ts deleted file mode 100644 index 07582e58..00000000 --- a/packages/control-hub/src/ControlHub.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ExpansionHub, ParentRevHub } from "@rev-robotics/expansion-hub"; - -export interface ControlHub extends ExpansionHub, ParentRevHub {} diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index 49ba71e6..ef4033c8 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -1,7 +1,7 @@ import { ControlHubInternal } from "./internal/ControlHub.js"; import { Adb, DeviceClient } from "@u4/adbkit"; import getPort from "get-port"; -import { ControlHub } from "./ControlHub.js"; +import { ControlHub } from "@rev-robotics/rev-hub-core"; export async function openConnectedControlHub(): Promise { try { diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index fdedcab7..d66f791e 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,3 +1,2 @@ export { openConnectedControlHub, openUsbControlHubs } from "./discovery.js"; -export * from "./ControlHub.js"; diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index ec7756b7..4f0d2b11 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -1,8 +1,7 @@ -import { ExpansionHub, ParentRevHub, RevHub, RevHubType } from "@rev-robotics/expansion-hub"; import { BulkInputData, DebugGroup, - DioDirection, + DigitalChannelDirection, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, @@ -17,7 +16,13 @@ import { import axios from "axios"; import semver from "semver"; import WebSocket from "isomorphic-ws"; -import { ControlHub, ParentControlHub } from "../ControlHub.js"; +import { + ControlHub, + ExpansionHub, + ParentRevHub, + RevHub, + RevHubType, +} from "@rev-robotics/rev-hub-core"; export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; @@ -107,7 +112,7 @@ export class ControlHubInternal implements ControlHub { throw new Error("not implemented"); } - async getDigitalDirection(dioPin: number): Promise { + async getDigitalDirection(dioPin: number): Promise { throw new Error("not implemented"); } @@ -273,7 +278,7 @@ export class ControlHubInternal implements ControlHub { throw new Error("not implemented"); } - setDigitalDirection(dioPin: number, direction: DioDirection): Promise { + setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { throw new Error("not implemented"); } diff --git a/packages/core/src/ControlHub.ts b/packages/core/src/ControlHub.ts new file mode 100644 index 00000000..01ce2a91 --- /dev/null +++ b/packages/core/src/ControlHub.ts @@ -0,0 +1,4 @@ +import { ExpansionHub } from "./ExpansionHub.js"; +import { ParentRevHub } from "./RevHub.js"; + +export interface ControlHub extends ExpansionHub, ParentRevHub {} diff --git a/packages/core/src/ExpansionHub.ts b/packages/core/src/ExpansionHub.ts index b4ef2bfa..463ba2b2 100644 --- a/packages/core/src/ExpansionHub.ts +++ b/packages/core/src/ExpansionHub.ts @@ -1,21 +1,21 @@ import { ParentRevHub, RevHub } from "./RevHub.js"; -import { ModuleStatus } from "./ModuleStatus.js"; -import { ModuleInterface } from "./ModuleInterface.js"; -import { Rgb } from "./Rgb.js"; -import { LedPattern } from "./LedPattern.js"; -import { DebugGroup } from "./DebugGroup.js"; -import { VerbosityLevel } from "./VerbosityLevel.js"; -import { BulkInputData } from "./BulkInputData.js"; -import { Version } from "./Version.js"; -import { DigitalState } from "./DigitalState.js"; -import { I2CSpeedCode } from "./I2CSpeedCode.js"; -import { I2CWriteStatus } from "./I2CWriteStatus.js"; -import { I2CReadStatus } from "./I2CReadStatus.js"; -import { PidCoefficients } from "./PidCoefficients.js"; -import { DigitalChannelDirection } from "./DigitalChannelDirection.js"; -import { MotorMode } from "./MotorMode.js"; -import { PidfCoefficients } from "./PidfCoefficients.js"; -import { ClosedLoopControlAlgorithm } from "./ClosedLoopControlAlgorithm.js"; +import {DigitalState} from "./DigitalState.js"; +import {ModuleInterface} from "./ModuleInterface.js"; +import {Rgb} from "./Rgb.js"; +import {LedPattern} from "./LedPattern.js"; +import {ModuleStatus} from "./ModuleStatus.js"; +import {DebugGroup} from "./DebugGroup.js"; +import {VerbosityLevel} from "./VerbosityLevel.js"; +import {Version} from "./Version.js"; +import {DigitalChannelDirection} from "./DigitalChannelDirection.js"; +import {I2CSpeedCode} from "./I2CSpeedCode.js"; +import {I2CWriteStatus} from "./I2CWriteStatus.js"; +import {I2CReadStatus} from "./I2CReadStatus.js"; +import {MotorMode} from "./MotorMode.js"; +import {PidCoefficients} from "./PidCoefficients.js"; +import {PidfCoefficients} from "./PidfCoefficients.js"; +import {ClosedLoopControlAlgorithm} from "./ClosedLoopControlAlgorithm.js"; +import {BulkInputData} from "./BulkInputData.js"; export type ParentExpansionHub = ParentRevHub & ExpansionHub; @@ -195,7 +195,7 @@ export interface ExpansionHub extends RevHub { ): Promise; writeI2CReadMultipleBytes( i2cChannel: number, - targetAddress: number, + slaveAddress: number, numBytesToRead: number, startAddress: number, ): Promise; diff --git a/packages/core/src/RevHub.ts b/packages/core/src/RevHub.ts index d1ed07ec..383bcced 100644 --- a/packages/core/src/RevHub.ts +++ b/packages/core/src/RevHub.ts @@ -15,7 +15,7 @@ export interface RevHub { * @param listener */ on(eventName: "error", listener: (error: Error) => void): RevHub; - close(): any; + close(): void; } export interface ParentRevHub extends RevHub { diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 5c86a3d2..11324309 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -1,7 +1,9 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + "esModuleInterop": true, "outDir": "./dist", - "rootDir": "./src" + "rootDir": "./src", + "target": "es2017" } } diff --git a/packages/expansion-hub/src/RevHubType.ts b/packages/expansion-hub/src/RevHubType.ts deleted file mode 100644 index de4220b4..00000000 --- a/packages/expansion-hub/src/RevHubType.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum RevHubType { - ExpansionHub, - ControlHub, -} diff --git a/packages/expansion-hub/src/internal/ExpansionHub.ts b/packages/expansion-hub/src/internal/ExpansionHub.ts index 450902ac..117eb73e 100644 --- a/packages/expansion-hub/src/internal/ExpansionHub.ts +++ b/packages/expansion-hub/src/internal/ExpansionHub.ts @@ -1,9 +1,3 @@ -import { - NackCode, - NativeRevHub, - RhspLibErrorCode, - Serial as SerialPort, -} from "@rev-robotics/rhsplib"; import { BulkInputData, ClosedLoopControlAlgorithm, @@ -11,8 +5,7 @@ import { DebugGroup, DigitalChannelDirection, DigitalState, - ExpansionHub, - GeneralSerialError, + ExpansionHub, GeneralSerialError, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, @@ -20,24 +13,24 @@ import { ModuleInterface, ModuleStatus, MotorMode, - nackCodeToError, - NoExpansionHubWithAddressError, + NackCode, nackCodeToError, NoExpansionHubWithAddressError, ParameterOutOfRangeError, ParentRevHub, PidCoefficients, PidfCoefficients, RevHub, RevHubType, - Rgb, - TimeoutError, + Rgb, TimeoutError, VerbosityLevel, - Version, + Version } from "@rev-robotics/rev-hub-core"; -import { closeSerialPort } from "../open-rev-hub.js"; -import { EventEmitter } from "events"; -import { RhspLibError } from "../errors/RhspLibError.js"; -import { startKeepAlive } from "../start-keep-alive.js"; -import { performance } from "perf_hooks"; +import {SerialPort} from "serialport"; +import {NativeRevHub, RhspLibErrorCode} from "@rev-robotics/rhsplib"; +import {EventEmitter} from "events"; +import {closeSerialPort} from "../open-rev-hub.js"; +import {RhspLibError} from "../errors/RhspLibError.js"; +import {performance} from "perf_hooks"; +import {startKeepAlive} from "../start-keep-alive.js"; export class ExpansionHubInternal implements ExpansionHub { constructor(isParent: true, serial: SerialPort, serialNumber: string); @@ -62,7 +55,7 @@ export class ExpansionHubInternal implements ExpansionHub { keepAliveTimer?: NodeJS.Timer; - type = RevHubType.ExpansionHub; + type: RevHubType = RevHubType.ExpansionHub; private emitter = new EventEmitter(); isParent(): this is ParentRevHub { diff --git a/packages/expansion-hub/src/open-rev-hub.ts b/packages/expansion-hub/src/open-rev-hub.ts index 23f1f8cc..43fe920c 100644 --- a/packages/expansion-hub/src/open-rev-hub.ts +++ b/packages/expansion-hub/src/open-rev-hub.ts @@ -13,7 +13,6 @@ import { InvalidSerialArguments, NoExpansionHubWithAddressError, ParentExpansionHub, - RevHub, SerialConfigurationError, SerialIoError, SerialParity, diff --git a/packages/sample/src/command/led.ts b/packages/sample/src/command/led.ts index 149ff151..0ab11ecf 100644 --- a/packages/sample/src/command/led.ts +++ b/packages/sample/src/command/led.ts @@ -1,8 +1,8 @@ import { createLedPattern, - ExpansionHub, LedPatternStep, -} from "@rev-robotics/rev-hub-core"; +} from "@rev-robotics/expansion-hub"; +import { ExpansionHub } from "@rev-robotics/rev-hub-core"; export async function ledPattern(hub: ExpansionHub, args: string[]) { function parse(step: string): LedPatternStep { diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 2d6ab3c3..99d49556 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,6 +1,7 @@ import { hubHierarchyToString } from "../HubStringify.js"; -import {ExpansionHub} from "@rev-robotics/rev-hub-core"; import { openConnectedControlHub, openUsbControlHubs } from "@rev-robotics/control-hub"; +import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub" export async function list() { let usbControlHubs = await openUsbControlHubs(); From 89e331dfc7676add09fc1f5973fd033a50e3ebf9 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 15:13:57 -0500 Subject: [PATCH 17/81] Move adbkit usage out of control hub module --- package-lock.json | 9 +--- packages/control-hub/package.json | 4 -- packages/control-hub/src/discovery.ts | 59 -------------------------- packages/control-hub/src/index.ts | 2 +- packages/core/src/index.ts | 1 + packages/sample/src/adb-setup.ts | 61 +++++++++++++++++++++++++++ packages/sample/src/command/list.ts | 3 +- 7 files changed, 66 insertions(+), 73 deletions(-) create mode 100644 packages/sample/src/adb-setup.ts diff --git a/package-lock.json b/package-lock.json index ce32c306..968cf419 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7779,20 +7779,16 @@ "version": "0.1.0", "dependencies": { "@rev-robotics/rev-hub-core": "*", - "@rev-robotics/rhsplib": "*", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", - "semver": "^7.5.1", - "serialport": "^10.5.0" + "semver": "^7.5.1" }, "devDependencies": { "@types/node": "^16.18.18", - "@types/node-forge": "^1.3.2", "@types/semver": "^7.5.0", "typescript": "^5.0.2" }, "peerDependencies": { - "@u4/adbkit": ">= 4.1.19", "get-port": "^6.1.2" } }, @@ -9156,14 +9152,11 @@ "version": "file:packages/control-hub", "requires": { "@rev-robotics/rev-hub-core": "*", - "@rev-robotics/rhsplib": "*", "@types/node": "^16.18.18", - "@types/node-forge": "^1.3.2", "@types/semver": "^7.5.0", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", "semver": "^7.5.1", - "serialport": "^10.5.0", "typescript": "^5.0.2" } }, diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index feac0164..2a2ae65e 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -4,21 +4,17 @@ "description": "High level library for the REV Robotics Control Hub", "main": "dist/index.js", "dependencies": { - "serialport": "^10.5.0", "isomorphic-ws": "^5.0.0", "axios": "^1.4.0", "semver": "^7.5.1", - "@rev-robotics/rhsplib": "*", "@rev-robotics/rev-hub-core": "*" }, "peerDependencies": { - "@u4/adbkit": ">= 4.1.19", "get-port": "^6.1.2" }, "devDependencies": { "@types/node": "^16.18.18", "@types/semver": "^7.5.0", - "@types/node-forge": "^1.3.2", "typescript": "^5.0.2" }, "scripts": { diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index ef4033c8..bb85d757 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -1,6 +1,4 @@ import { ControlHubInternal } from "./internal/ControlHub.js"; -import { Adb, DeviceClient } from "@u4/adbkit"; -import getPort from "get-port"; import { ControlHub } from "@rev-robotics/rev-hub-core"; export async function openConnectedControlHub(): Promise { @@ -11,43 +9,6 @@ export async function openConnectedControlHub(): Promise } } -export async function openUsbControlHubs(): Promise { - let adbClient = Adb.createClient(); - let controlHubs: ControlHub[] = []; - - let devices = await adbClient.listDevices(); - for (const device of devices) { - let deviceClient = device.getClient(); - let isHub = await isControlHub(deviceClient); - if (isHub) { - let port = await configureHubTcp(deviceClient); - let serialNumber = device.id; - - let hub = new ControlHubInternal(serialNumber); - await hub.open("127.0.0.1", (port + 1).toString()); - controlHubs.push(hub); - } - } - - return controlHubs; -} - -async function configureHubTcp(deviceClient: DeviceClient): Promise { - let port = await findAdjacentPorts(); - await deviceClient.forward(`tcp:${port}`, `tcp:8080`); - await deviceClient.forward(`tcp:${port + 1}`, `tcp:8081`); - - return port; -} - -async function isControlHub(deviceClient: DeviceClient): Promise { - let serialasusb = await deviceClient.execOut( - "getprop persist.ftcandroid.serialasusb", - "utf8", - ); - return serialasusb.startsWith("true"); -} - async function createWiFiControlHub(): Promise { let hub = new ControlHubInternal("Placeholder"); @@ -59,23 +20,3 @@ async function createWiFiControlHub(): Promise { return hub; } - -/** - * Returns the first of two adjacent ports. - * @param host - */ -export async function findAdjacentPorts(host: string = "127.0.0.1"): Promise { - try { - //const getPort = (await import("get-port")).default; - let port = await getPort({ host: host }); - let adjacent = await getPort({ host: host, port: port + 1 }); - if (adjacent === port + 1) return port; - else { - return await findAdjacentPorts(host); - } - } catch (e) { - console.log("Got error checking ports"); - console.log(e); - throw e; - } -} diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index d66f791e..14db8f4e 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,2 +1,2 @@ -export { openConnectedControlHub, openUsbControlHubs } from "./discovery.js"; +export { openConnectedControlHub } from "./discovery.js"; diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 01795b0e..51e02a79 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -2,6 +2,7 @@ export * from "./nack-errors/nack-codes.js"; export * from "./ExpansionHub.js"; export * from "./serial-errors.js"; export * from "./RevHub.js"; +export * from "./ControlHub.js" export * from "./RevHubType.js"; export * from "./led-pattern.js"; export * from "./BulkInputData.js"; diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts new file mode 100644 index 00000000..f526a006 --- /dev/null +++ b/packages/sample/src/adb-setup.ts @@ -0,0 +1,61 @@ +import { Adb, DeviceClient } from "@u4/adbkit"; +import getPort from "get-port"; +import { ControlHub } from "@rev-robotics/rev-hub-core"; +import { ControlHubInternal } from "@rev-robotics/control-hub/dist/internal/ControlHub.js"; + +export async function openUsbControlHubs(): Promise { + let adbClient = Adb.createClient(); + let controlHubs: ControlHub[] = []; + + let devices = await adbClient.listDevices(); + for (const device of devices) { + let deviceClient = device.getClient(); + let isHub = await isControlHub(deviceClient); + if (isHub) { + let port = await configureHubTcp(deviceClient); + let serialNumber = device.id; + + let hub = new ControlHubInternal(serialNumber); + await hub.open("127.0.0.1", (port + 1).toString()); + controlHubs.push(hub); + } + } + + return controlHubs; +} + +async function isControlHub(deviceClient: DeviceClient): Promise { + let serialasusb = await deviceClient.execOut( + "getprop persist.ftcandroid.serialasusb", + "utf8", + ); + return serialasusb.startsWith("true"); +} + +async function configureHubTcp(deviceClient: DeviceClient): Promise { + let port = await findAdjacentPorts(); + await deviceClient.forward(`tcp:${port}`, `tcp:8080`); + await deviceClient.forward(`tcp:${port + 1}`, `tcp:8081`); + + return port; +} + +/** + * Returns the first of two adjacent ports. + * @param host + */ +export async function findAdjacentPorts(host: string = "127.0.0.1"): Promise { + try { + //const getPort = (await import("get-port")).default; + let port = await getPort({ host: host }); + let adjacent = await getPort({ host: host, port: port + 1 }); + if (adjacent === port + 1) return port; + else { + return await findAdjacentPorts(host); + } + } catch (e) { + console.log("Got error checking ports"); + console.log(e); + throw e; + } +} diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 99d49556..f1869951 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,7 +1,8 @@ import { hubHierarchyToString } from "../HubStringify.js"; -import { openConnectedControlHub, openUsbControlHubs } from "@rev-robotics/control-hub"; +import { openConnectedControlHub } from "@rev-robotics/control-hub"; import { ExpansionHub } from "@rev-robotics/rev-hub-core"; import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub" +import { openUsbControlHubs } from "../adb-setup.js"; export async function list() { let usbControlHubs = await openUsbControlHubs(); From c957a2626c5b93318df487e2591a6427fcc88a49 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 15:23:01 -0500 Subject: [PATCH 18/81] Remove override of target --- packages/control-hub/tsconfig.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/control-hub/tsconfig.json b/packages/control-hub/tsconfig.json index 11324309..5c86a3d2 100644 --- a/packages/control-hub/tsconfig.json +++ b/packages/control-hub/tsconfig.json @@ -1,9 +1,7 @@ { "extends": "../../tsconfig.json", "compilerOptions": { - "esModuleInterop": true, "outDir": "./dist", - "rootDir": "./src", - "target": "es2017" + "rootDir": "./src" } } From 1ba650d19b3fd3fdcaa1ade55a751ac4e038935a Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 15:30:49 -0500 Subject: [PATCH 19/81] Add note on dependencies in README --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 8b459165..ef8b725d 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,24 @@ This project enables Node.js applications to control devices that speak the REV Hub Serial Protocol (such as the REV Robotics Expansion Hub). +## Control Hub dependencies + +The Control Hub package has two optional dependencies. + +### ws + +If you are using node.js and wish to communicate +with a Control Hub via WiFi, you will need to add +a dependency on [ws](https://www.npmjs.com/package/ws). + +### adbkit + +If you wish to communicate with a Control Hub over +USB, you will need to set up port forwarding. This +requires a dependency on [adbkit](https://www.npmjs.com/package/adbkit). +See [adbkit setup](packages/sample/src/adb-setup.ts) +for an example of setting up port forwarding. + ## Package structure This project uses [lerna](https://lerna.js.org) for From 8952fb5c9fece7f424a615080a999464bd09efca Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 30 May 2023 15:33:55 -0500 Subject: [PATCH 20/81] loosen version requirement for get-port --- package-lock.json | 2 +- packages/control-hub/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 968cf419..66614306 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7789,7 +7789,7 @@ "typescript": "^5.0.2" }, "peerDependencies": { - "get-port": "^6.1.2" + "get-port": "6.x" } }, "packages/core": { diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 2a2ae65e..f48e82c7 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -10,7 +10,7 @@ "@rev-robotics/rev-hub-core": "*" }, "peerDependencies": { - "get-port": "^6.1.2" + "get-port": "6.x" }, "devDependencies": { "@types/node": "^16.18.18", From 00cf60e9bffcd0db299f4afc46386b9b2aaca1b9 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Mon, 5 Jun 2023 14:34:12 -0500 Subject: [PATCH 21/81] Send address in commands --- packages/control-hub/src/internal/ControlHub.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 4f0d2b11..e8d75321 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -70,7 +70,10 @@ export class ControlHubInternal implements ControlHub { return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { - this.moduleAddress = await this.sendCommand("getModuleAddress", {}); + this.moduleAddress = await this.sendCommand("getModuleAddress", { + serialNumber: "Embedded", + moduleAddress: 173, + }); resolve(); }); }); From 5df21bfbaec30298310f8c3978973760f1581ff1 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Mon, 5 Jun 2023 17:03:26 -0500 Subject: [PATCH 22/81] Send commands when control hub methods called --- packages/control-hub/src/index.ts | 11 + .../control-hub/src/internal/ControlHub.ts | 473 ++++++++++++++---- packages/sample/src/adb-setup.ts | 5 +- 3 files changed, 379 insertions(+), 110 deletions(-) diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index 14db8f4e..14bf7881 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,2 +1,13 @@ +import { ControlHubInternal } from "./internal/ControlHub.js"; +import { ControlHub } from "@rev-robotics/rev-hub-core"; export { openConnectedControlHub } from "./discovery.js"; + +export async function openControlHub( + serialNumber: string, + port: number, +): Promise { + let hub = new ControlHubInternal(serialNumber); + await hub.open("127.0.0.1", (port + 1).toString()); + return hub; +} diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index e8d75321..e06e4f41 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -1,28 +1,24 @@ import { BulkInputData, + ClosedLoopControlAlgorithm, + ControlHub, DebugGroup, - DigitalChannelDirection, + DigitalChannelDirection, ExpansionHub, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, LedPattern, ModuleInterface, ModuleStatus, - PidCoefficients, + PidCoefficients, RevHub, + RevHubType, Rgb, VerbosityLevel, Version, -} from "@rev-robotics/rhsplib"; +} from "@rev-robotics/rev-hub-core"; import axios from "axios"; import semver from "semver"; import WebSocket from "isomorphic-ws"; -import { - ControlHub, - ExpansionHub, - ParentRevHub, - RevHub, - RevHubType, -} from "@rev-robotics/rev-hub-core"; export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; @@ -108,27 +104,55 @@ export class ControlHubInternal implements ControlHub { } async getBulkInputData(): Promise { + let result = await this.sendCommand("getBulkInputData", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); throw new Error("not implemented"); } - getDigitalAllInputs(): Promise { - throw new Error("not implemented"); + async getDigitalAllInputs(): Promise { + return await this.sendCommand("getAllDigitalInputs", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } async getDigitalDirection(dioPin: number): Promise { - throw new Error("not implemented"); + let isOutput = await this.sendCommand("getDigitalDirection", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + channel: dioPin, + }); + + return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; } - getDigitalSingleInput(dioPin: number): Promise { - throw new Error("not implemented"); + async getDigitalSingleInput(dioPin: number): Promise { + return await this.sendCommand("getDigitalInput", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + channel: dioPin, + }); } - getFTDIResetControl(): Promise { - throw new Error("not implemented"); + async getFTDIResetControl(): Promise { + return await this.sendCommand("getFtdiResetControl", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - getI2CChannelConfiguration(i2cChannel: number): Promise { - throw new Error("not implemented"); + async getI2CChannelConfiguration(i2cChannel: number): Promise { + let speedCode = await this.sendCommand("getI2CChannelConfiguration", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + channel: i2cChannel, + }); + + return speedCode == 1 + ? I2CSpeedCode.SpeedCode400_Kbps + : I2CSpeedCode.SpeedCode100_Kbps; } getI2CReadStatus(i2cChannel: number): Promise { @@ -139,95 +163,199 @@ export class ControlHubInternal implements ControlHub { throw new Error("not implemented"); } - getInterfacePacketID(interfaceName: string, functionNumber: number): Promise { - return Promise.resolve(0); + async getInterfacePacketID( + interfaceName: string, + functionNumber: number, + ): Promise { + return await this.sendCommand("getInterfacePacketId", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + interfaceName: interfaceName, + functionNumber: functionNumber, + }); } - getModuleLedColor(): Promise { - throw new Error("not implemented"); + async getModuleLedColor(): Promise { + let result: { r: number; g: number; b: number } = await this.sendCommand( + "getLedColor", + { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }, + ); + + return { + red: result.r, + green: result.g, + blue: result.b, + }; } getModuleLedPattern(): Promise { throw new Error("not implemented"); } - getModuleStatus(clearStatusAfterResponse: boolean): Promise { - throw new Error("not implemented"); + async getModuleStatus(clearStatusAfterResponse: boolean): Promise { + return await this.sendCommand("getModuleStatus", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - getMotorAtTarget(motorChannel: number): Promise { - return Promise.resolve(false); + async getMotorAtTarget(motorChannel: number): Promise { + return await this.sendCommand("getIsMotorAtTarget", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { - return Promise.resolve(0); + async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { + return await this.sendCommand("getMotorAlertLevel", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - getMotorChannelEnable(motorChannel: number): Promise { - return Promise.resolve(false); + async getMotorChannelEnable(motorChannel: number): Promise { + return await this.sendCommand("getMotorChannelEnable", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - getMotorChannelMode( + async getMotorChannelMode( motorChannel: number, ): Promise<{ motorMode: number; floatAtZero: boolean }> { - return Promise.resolve({ floatAtZero: false, motorMode: 0 }); + return await this.sendCommand("getMotorMode", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - getMotorConstantPower(motorChannel: number): Promise { - return Promise.resolve(0); + async getMotorConstantPower(motorChannel: number): Promise { + return await this.sendCommand("getMotorConstantPower", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - getMotorEncoderPosition(motorChannel: number): Promise { - return Promise.resolve(0); + async getMotorEncoderPosition(motorChannel: number): Promise { + return await this.sendCommand("getMotorEncoderPosition", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - getMotorPIDCoefficients( + async getMotorPIDCoefficients( motorChannel: number, motorMode: number, ): Promise { - throw new Error("not implemented"); + let result: { p: number; i: number; d: number } = await this.sendCommand( + "getMotorPidCoefficients", + { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }, + ); + + return { + p: result.p, + i: result.i, + d: result.d, + algorithm: ClosedLoopControlAlgorithm.Pid + }; } - getMotorTargetPosition( + async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { - return Promise.resolve({ targetPosition: 0, targetTolerance: 0 }); + let result: { targetPositionCounts: number; targetToleranceCounts: number } = + await this.sendCommand("getMotorTargetPosition", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); + + return { + targetPosition: result.targetPositionCounts, + targetTolerance: result.targetToleranceCounts, + }; } - getMotorTargetVelocity(motorChannel: number): Promise { - return Promise.resolve(0); + async getMotorTargetVelocity(motorChannel: number): Promise { + return await this.sendCommand("getMotorTargetVelocity", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - getPhoneChargeControl(): Promise { - return Promise.resolve(false); + async getPhoneChargeControl(): Promise { + return await this.sendCommand("getPhoneChargeControl", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - getServoConfiguration(servoChannel: number): Promise { - return Promise.resolve(0); + async getServoConfiguration(servoChannel: number): Promise { + return await this.sendCommand("getServoConfiguration", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + servoChannel: servoChannel, + }); } - getServoEnable(servoChannel: number): Promise { - return Promise.resolve(false); + async getServoEnable(servoChannel: number): Promise { + return await this.sendCommand("getServoEnable", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + servoChannel: servoChannel, + }); } - getServoPulseWidth(servoChannel: number): Promise { - return Promise.resolve(0); + async getServoPulseWidth(servoChannel: number): Promise { + return await this.sendCommand("getServoPulseWidth", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + servoChannel: servoChannel, + }); } - injectDataLogHint(hintText: string): Promise { - throw new Error("not implemented"); + async injectDataLogHint(hintText: string): Promise { + await this.sendCommand("injectDebugLogHint", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + hint: hintText, + }); } isExpansionHub(): this is ExpansionHub { - throw new Error("not implemented"); + return true; } on(eventName: "error", listener: (error: Error) => void): RevHub { throw new Error("not implemented"); } - queryInterface(interfaceName: string): Promise { - throw new Error("not implemented"); + async queryInterface(interfaceName: string): Promise { + let result: { name: string; firstPacketId: number; numberIds: number } = + await this.sendCommand("queryInterface", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + interfaceName: interfaceName, + }); + + return { + name: result.name, + firstPacketID: result.firstPacketId, + numberIDValues: result.numberIds, + }; } readI2CMultipleBytes( @@ -242,27 +370,37 @@ export class ControlHubInternal implements ControlHub { throw new Error("not implemented"); } - readVersion(): Promise { + async readVersion(): Promise { + let versionString = await this.readVersionString(); + //ToDo(landry) parse version string throw new Error("not implemented"); } - readVersionString(): Promise { - return Promise.resolve(""); + async readVersionString(): Promise { + return await this.sendCommand("readVersionString", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - resetMotorEncoder(motorChannel: number): Promise { - throw new Error("not implemented"); + async resetMotorEncoder(motorChannel: number): Promise { + await this.sendCommand("resetMotorEncoder", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); } - sendFailSafe(): Promise { - throw new Error("not implemented"); + async sendFailSafe(): Promise { + await this.sendCommand("readVersionString", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - sendKeepAlive(): Promise { - throw new Error("not implemented"); - } + async sendKeepAlive(): Promise {} - sendReadCommand(packetTypeID: number, payload: number[]): Promise { + async sendReadCommand(packetTypeID: number, payload: number[]): Promise { return Promise.resolve([]); } @@ -270,105 +408,226 @@ export class ControlHubInternal implements ControlHub { return Promise.resolve([]); } - setDebugLogLevel( + async setDebugLogLevel( debugGroup: DebugGroup, verbosityLevel: VerbosityLevel, ): Promise { - throw new Error("not implemented"); + await this.sendCommand("readVersionString", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + debugGroup: debugGroup, + verbosityLevel: verbosityLevel, + }); } - setDigitalAllOutputs(bitPackedField: number): Promise { - throw new Error("not implemented"); + async setDigitalAllOutputs(bitPackedField: number): Promise { + await this.sendCommand("readVersionString", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + bitField: bitPackedField, + }); } - setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { - throw new Error("not implemented"); + async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { + await this.sendCommand("readVersionString", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + pin: dioPin, + isOutput: direction == DigitalChannelDirection.Output, + }); } - setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { - throw new Error("not implemented"); + async setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { + await this.sendCommand("readVersionString", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + pin: dioPin, + value: value ?? false, + }); } - setFTDIResetControl(ftdiResetControl: boolean): Promise { - throw new Error("not implemented"); + async setFTDIResetControl(ftdiResetControl: boolean): Promise { + await this.sendCommand("setFtdiResetControl", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); } - setI2CChannelConfiguration( + async setI2CChannelConfiguration( i2cChannel: number, speedCode: I2CSpeedCode, ): Promise { - throw new Error("not implemented"); + await this.sendCommand("setI2CChannelConfiguration", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + i2cChannel: i2cChannel, + speedCode: speedCode, + }); } - setModuleLedColor(red: number, green: number, blue: number): Promise { - throw new Error("not implemented"); + async setModuleLedColor(red: number, green: number, blue: number): Promise { + await this.sendCommand("setLedColor", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + r: red, + g: green, + b: blue, + }); } - setModuleLedPattern(ledPattern: LedPattern): Promise { - throw new Error("not implemented"); + async setModuleLedPattern(ledPattern: LedPattern): Promise { + await this.sendCommand("setLedColor", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + rgbtPatternStep0: ledPattern.rgbtPatternStep0, + rgbtPatternStep1: ledPattern.rgbtPatternStep1, + rgbtPatternStep2: ledPattern.rgbtPatternStep2, + rgbtPatternStep3: ledPattern.rgbtPatternStep3, + rgbtPatternStep4: ledPattern.rgbtPatternStep4, + rgbtPatternStep5: ledPattern.rgbtPatternStep5, + rgbtPatternStep6: ledPattern.rgbtPatternStep6, + rgbtPatternStep7: ledPattern.rgbtPatternStep7, + rgbtPatternStep8: ledPattern.rgbtPatternStep8, + rgbtPatternStep9: ledPattern.rgbtPatternStep9, + rgbtPatternStep10: ledPattern.rgbtPatternStep10, + rgbtPatternStep11: ledPattern.rgbtPatternStep11, + rgbtPatternStep12: ledPattern.rgbtPatternStep12, + rgbtPatternStep13: ledPattern.rgbtPatternStep13, + rgbtPatternStep14: ledPattern.rgbtPatternStep14, + rgbtPatternStep15: ledPattern.rgbtPatternStep15, + }); } - setMotorChannelCurrentAlertLevel( + async setMotorChannelCurrentAlertLevel( motorChannel: number, currentLimit_mA: number, ): Promise { - throw new Error("not implemented"); + await this.sendCommand("setMotorAlertLevel", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + currentLimit_mA: currentLimit_mA, + }); } - setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { - throw new Error("not implemented"); + async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { + await this.sendCommand("setMotorEnabled", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + enable: enable, + }); } - setMotorChannelMode( + async setMotorChannelMode( motorChannel: number, motorMode: number, floatAtZero: boolean, ): Promise { - throw new Error("not implemented"); + await this.sendCommand("setMotorChannelMode", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + motorMode: motorMode, + floatAtZero: floatAtZero, + }); } - setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { - throw new Error("not implemented"); + async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { + await this.sendCommand("setMotorConstantPower", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + motorPower: powerLevel, + }); } - setMotorPIDCoefficients( + async setMotorPIDCoefficients( motorChannel: number, motorMode: number, pid: PidCoefficients, ): Promise { - throw new Error("not implemented"); + await this.sendCommand("setMotorPidCoefficients", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + motorMode: motorMode, + p: pid.p, + i: pid.i, + d: pid.d, + }); } - setMotorTargetPosition( + async setMotorTargetPosition( motorChannel: number, targetPosition_counts: number, targetTolerance_counts: number, ): Promise { - throw new Error("not implemented"); + await this.sendCommand("setMotorTargetPosition", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + targetPositionCounts: targetPosition_counts, + targetToleranceCounts: targetTolerance_counts, + }); } - setMotorTargetVelocity(motorChannel: number, velocity_cps: number): Promise { - throw new Error("not implemented"); + async setMotorTargetVelocity( + motorChannel: number, + velocity_cps: number, + ): Promise { + await this.sendCommand("setMotorTargetVelocity", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + velocityCps: velocity_cps, + }); } - setNewModuleAddress(newModuleAddress: number): Promise { - throw new Error("not implemented"); + async setNewModuleAddress(newModuleAddress: number): Promise { + await this.sendCommand("setNewModuleAddress", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + address: newModuleAddress, + }); } - setPhoneChargeControl(chargeEnable: boolean): Promise { - throw new Error("not implemented"); + async setPhoneChargeControl(chargeEnable: boolean): Promise { + await this.sendCommand("setPhoneChargeControl", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + enabled: chargeEnable, + }); } - setServoConfiguration(servoChannel: number, framePeriod: number): Promise { - throw new Error("not implemented"); + async setServoConfiguration( + servoChannel: number, + framePeriod: number, + ): Promise { + await this.sendCommand("setServoConfiguration", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + servoChannel: servoChannel, + framePeriod: framePeriod, + }); } - setServoEnable(servoChannel: number, enable: boolean): Promise { - throw new Error("not implemented"); + async setServoEnable(servoChannel: number, enable: boolean): Promise { + await this.sendCommand("setServoEnable", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + servoChannel: servoChannel, + enabled: enable, + }); } - setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { - throw new Error("not implemented"); + async setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { + await this.sendCommand("setServoPulseWidth", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + servoChannel: servoChannel, + pulseWidth: pulseWidth, + }); } writeI2CMultipleBytes( diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index f526a006..61db9ef3 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -1,7 +1,7 @@ import { Adb, DeviceClient } from "@u4/adbkit"; import getPort from "get-port"; import { ControlHub } from "@rev-robotics/rev-hub-core"; -import { ControlHubInternal } from "@rev-robotics/control-hub/dist/internal/ControlHub.js"; +import { openControlHub } from "@rev-robotics/control-hub"; export async function openUsbControlHubs(): Promise { let adbClient = Adb.createClient(); @@ -15,8 +15,7 @@ export async function openUsbControlHubs(): Promise { let port = await configureHubTcp(deviceClient); let serialNumber = device.id; - let hub = new ControlHubInternal(serialNumber); - await hub.open("127.0.0.1", (port + 1).toString()); + let hub = await openControlHub(serialNumber, port); controlHubs.push(hub); } } From 31fef3c461f3022e62c99f56e35f3902e5d5804d Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 11:16:37 -0500 Subject: [PATCH 23/81] Use control hubs for commands and fix incorrect key --- packages/control-hub/package.json | 1 + .../control-hub/src/internal/ControlHub.ts | 88 ++++++++++++++++--- packages/sample/src/command/led.ts | 6 +- packages/sample/src/command/servo.ts | 9 +- packages/sample/src/main.ts | 3 +- 5 files changed, 79 insertions(+), 28 deletions(-) diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index f48e82c7..08750822 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "description": "High level library for the REV Robotics Control Hub", "main": "dist/index.js", + "type": "module", "dependencies": { "isomorphic-ws": "^5.0.0", "axios": "^1.4.0", diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index e06e4f41..cad13cef 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -3,22 +3,22 @@ import { ClosedLoopControlAlgorithm, ControlHub, DebugGroup, - DigitalChannelDirection, ExpansionHub, + DigitalChannelDirection, DigitalState, ExpansionHub, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, LedPattern, ModuleInterface, - ModuleStatus, - PidCoefficients, RevHub, + ModuleStatus, MotorMode, ParentRevHub, + PidCoefficients, PidfCoefficients, RevHub, RevHubType, Rgb, VerbosityLevel, Version, } from "@rev-robotics/rev-hub-core"; import axios from "axios"; -import semver from "semver"; import WebSocket from "isomorphic-ws"; +import semver = require("semver/preload.js"); export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; @@ -49,8 +49,8 @@ export class ControlHubInternal implements ControlHub { this.webSocketConnection.on("message", (data) => { let rawMessage = JSON.parse(data.toString()); - if (rawMessage.key !== undefined) { - let key = rawMessage.key; + if (rawMessage.commandKey !== undefined) { + let key = rawMessage.commandKey; let callback = this.currentActiveCommands.get(key); let response = rawMessage.response @@ -128,14 +128,6 @@ export class ControlHubInternal implements ControlHub { return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; } - async getDigitalSingleInput(dioPin: number): Promise { - return await this.sendCommand("getDigitalInput", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - channel: dioPin, - }); - } - async getFTDIResetControl(): Promise { return await this.sendCommand("getFtdiResetControl", { serialNumber: this.serialNumber, @@ -261,6 +253,7 @@ export class ControlHubInternal implements ControlHub { serialNumber: this.serialNumber, moduleAddress: this.moduleAddress, motorChannel: motorChannel, + motorMode: motorMode, }, ); @@ -688,4 +681,71 @@ export class ControlHubInternal implements ControlHub { addChildByAddress(moduleAddress: number): Promise { throw new Error("not implemented"); } + + get5VBusVoltage(): Promise { + return Promise.resolve(0); + } + + getAllDigitalInputs(): Promise { + return Promise.resolve(0); + } + + getAnalogInput(channel: number): Promise { + return Promise.resolve(0); + } + + getBatteryCurrent(): Promise { + return Promise.resolve(0); + } + + getBatteryVoltage(): Promise { + return Promise.resolve(0); + } + + getDigitalBusCurrent(): Promise { + return Promise.resolve(0); + } + + async getDigitalInput(digitalChannel: number): Promise { + return await this.sendCommand("getDigitalInput", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + channel: digitalChannel, + }); + } + + getI2CCurrent(): Promise { + return Promise.resolve(0); + } + + getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { + return this.getMotorPIDCoefficients(motorChannel, motorMode); + } + + getMotorCurrent(motorChannel: number): Promise { + return Promise.resolve(0); + } + + getServoCurrent(): Promise { + return Promise.resolve(0); + } + + getTemperature(): Promise { + return Promise.resolve(0); + } + + setAllDigitalOutputs(bitPackedField: number): Promise { + return Promise.resolve(undefined); + } + + setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { + return Promise.resolve(undefined); + } + + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid, pid: PidCoefficients): Promise; + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { + return Promise.resolve(undefined); + } } diff --git a/packages/sample/src/command/led.ts b/packages/sample/src/command/led.ts index 0ab11ecf..d023fc88 100644 --- a/packages/sample/src/command/led.ts +++ b/packages/sample/src/command/led.ts @@ -1,8 +1,4 @@ -import { - createLedPattern, - LedPatternStep, -} from "@rev-robotics/expansion-hub"; -import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import {createLedPattern, ExpansionHub, LedPatternStep} from "@rev-robotics/rev-hub-core"; export async function ledPattern(hub: ExpansionHub, args: string[]) { function parse(step: string): LedPatternStep { diff --git a/packages/sample/src/command/servo.ts b/packages/sample/src/command/servo.ts index 140ad98a..a4a92597 100644 --- a/packages/sample/src/command/servo.ts +++ b/packages/sample/src/command/servo.ts @@ -1,11 +1,6 @@ -import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import {ExpansionHub} from "@rev-robotics/rev-hub-core"; -export async function runServo( - hub: ExpansionHub, - channel: number, - pulseWidth: number, - framePeriod: number, -) { +export async function runServo(hub: ExpansionHub, channel: number, pulseWidth: number, framePeriod: number) { await hub.setServoConfiguration(channel, framePeriod); await hub.setServoPulseWidth(channel, pulseWidth); await hub.setServoEnable(channel, true); diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index fc7439d8..543ffe37 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -84,8 +84,7 @@ program .command("list") .description("List all connected expansion hubs") .action(async () => { - let hubs = await openConnectedExpansionHubs(); - await list(hubs); + await list(); }); program From e028ce96cbe7b72461a18c0e981b12c92a8c88b8 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 11:41:25 -0500 Subject: [PATCH 24/81] apply changes to be compatible with new manual control changes --- packages/control-hub/src/internal/ControlHub.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index cad13cef..0d5a91a0 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -66,6 +66,14 @@ export class ControlHubInternal implements ControlHub { return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { + console.log("Starting manual control op mode"); + let apiVersion: { majorVersion: string; minorVersion: string } = + await this.sendCommand("start", {}); + + console.log( + `API version is ${apiVersion.majorVersion}.${apiVersion.minorVersion}`, + ); + this.moduleAddress = await this.sendCommand("getModuleAddress", { serialNumber: "Embedded", moduleAddress: 173, @@ -96,7 +104,9 @@ export class ControlHubInternal implements ControlHub { } close(): void { - this.webSocketConnection.close(); + this.sendCommand("stop", {}).then(() => { + this.webSocketConnection.close(); + }); } getADC(): Promise { @@ -655,10 +665,11 @@ export class ControlHubInternal implements ControlHub { commandPayload: JSON.stringify(params), }; let payload = { - namespace: "ManualControl", + namespace: "MC", type: type, payload: JSON.stringify(messagePayload), }; + this.webSocketConnection?.send(JSON.stringify(payload)); return new Promise((resolve, reject) => { From 8971f0b506a1ac4d1b17baa3461f80a40a9a907a Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 13:54:55 -0500 Subject: [PATCH 25/81] add timeout to control hub websocket commands --- .../control-hub/src/internal/ControlHub.ts | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 0d5a91a0..b0304423 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -1,24 +1,29 @@ +import axios from "axios"; +import semver from "semver"; +import WebSocket from "isomorphic-ws"; import { + ControlHub, + ExpansionHub, + ParentRevHub, + RevHub, + RevHubType, + TimeoutError, BulkInputData, ClosedLoopControlAlgorithm, - ControlHub, DebugGroup, - DigitalChannelDirection, DigitalState, ExpansionHub, + DigitalChannelDirection, DigitalState, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, LedPattern, ModuleInterface, - ModuleStatus, MotorMode, ParentRevHub, - PidCoefficients, PidfCoefficients, RevHub, - RevHubType, + ModuleStatus, MotorMode, + PidCoefficients, PidfCoefficients, Rgb, VerbosityLevel, Version, } from "@rev-robotics/rev-hub-core"; -import axios from "axios"; -import WebSocket from "isomorphic-ws"; -import semver = require("semver/preload.js"); +import { clearTimeout } from "timers"; export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; @@ -658,7 +663,7 @@ export class ControlHubInternal implements ControlHub { throw new Error("not implemented"); } - async sendCommand(type: string, params: P): Promise { + async sendCommand(type: string, params: P, timeout: number = 1000): Promise { let key = 0; let messagePayload = { key: key, @@ -672,7 +677,7 @@ export class ControlHubInternal implements ControlHub { this.webSocketConnection?.send(JSON.stringify(payload)); - return new Promise((resolve, reject) => { + let callbackPromise: Promise = new Promise((resolve, reject) => { this.currentActiveCommands.set(key, (response, error) => { if (response !== undefined) { resolve(response); @@ -683,6 +688,17 @@ export class ControlHubInternal implements ControlHub { } }); }); + + let timer!: NodeJS.Timer; + let timeoutPromise: Promise = new Promise((_, reject) => { + timer = setTimeout(() => { + reject(new TimeoutError()); + }, timeout); + }); + + return await Promise.race([callbackPromise, timeoutPromise]).finally(() => { + clearTimeout(timer); + }); } addChild(hub: RevHub): void { From bafff3e2f7d947ff3088107cf28bd6891239c0a2 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 13:56:39 -0500 Subject: [PATCH 26/81] Add todo for closing (and resetting op mode) when websocket is closed --- packages/control-hub/src/internal/ControlHub.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index b0304423..2f3acd31 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -69,6 +69,8 @@ export class ControlHubInternal implements ControlHub { } }); + //Todo(landry): determine if we should call close() on webSocketConnection.on("close") + return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { console.log("Starting manual control op mode"); From d2bb88ac46c8d0523769fc47efed78c6b6e8601e Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 15:03:48 -0500 Subject: [PATCH 27/81] Track whether the control hub is connected --- packages/control-hub/src/internal/ControlHub.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 2f3acd31..004f1935 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -34,6 +34,11 @@ export class ControlHubInternal implements ControlHub { readonly serialNumber: string; readonly children: ReadonlyArray = []; + /** + * Whether the websocket is currently open. + */ + isConnected = false; + keyGenerator = 0; currentActiveCommands = new Map< any, @@ -69,10 +74,20 @@ export class ControlHubInternal implements ControlHub { } }); - //Todo(landry): determine if we should call close() on webSocketConnection.on("close") + this.webSocketConnection.on("close", () => { + console.log(`Connection was closed`); + this.isConnected = false; + }); + + this.webSocketConnection.on("error", (_: WebSocket, err: Error) => { + console.log("Websocket error"); + console.log(err); + this.isConnected = false; + }); return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { + this.isConnected = true; console.log("Starting manual control op mode"); let apiVersion: { majorVersion: string; minorVersion: string } = await this.sendCommand("start", {}); From 4f3586235322e5af101362de61b060251cbe7009 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 15:07:30 -0500 Subject: [PATCH 28/81] convert some methods to private --- packages/control-hub/src/internal/ControlHub.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 004f1935..d657f943 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -30,7 +30,6 @@ export class ControlHubInternal implements ControlHub { moduleAddress: number = 0; responseTimeoutMs: number = 0; type: RevHubType = RevHubType.ControlHub; - webSocketConnection!: WebSocket; readonly serialNumber: string; readonly children: ReadonlyArray = []; @@ -39,8 +38,9 @@ export class ControlHubInternal implements ControlHub { */ isConnected = false; - keyGenerator = 0; - currentActiveCommands = new Map< + private webSocketConnection!: WebSocket; + private keyGenerator = 0; + private currentActiveCommands = new Map< any, (response: any | undefined, error: any | undefined) => void >(); From bbaedb15f86b711ac7986df218b653845db1b1d3 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 15:44:32 -0500 Subject: [PATCH 29/81] remove logs --- packages/control-hub/src/internal/ControlHub.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index d657f943..1cbb6561 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -88,14 +88,9 @@ export class ControlHubInternal implements ControlHub { return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { this.isConnected = true; - console.log("Starting manual control op mode"); let apiVersion: { majorVersion: string; minorVersion: string } = await this.sendCommand("start", {}); - console.log( - `API version is ${apiVersion.majorVersion}.${apiVersion.minorVersion}`, - ); - this.moduleAddress = await this.sendCommand("getModuleAddress", { serialNumber: "Embedded", moduleAddress: 173, From 9a7d27f6d4940af924e1e543a67302c20dcf472c Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 8 Jun 2023 15:52:12 -0500 Subject: [PATCH 30/81] update servo command --- packages/control-hub/src/internal/ControlHub.ts | 14 +++++++++++++- packages/sample/src/command/servo.ts | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 1cbb6561..0a608f23 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -33,6 +33,9 @@ export class ControlHubInternal implements ControlHub { readonly serialNumber: string; readonly children: ReadonlyArray = []; + private supportedManualControlMajorVersion = 0; + private supportedManualControlMinorVersion = 1; + /** * Whether the websocket is currently open. */ @@ -88,9 +91,18 @@ export class ControlHubInternal implements ControlHub { return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { this.isConnected = true; - let apiVersion: { majorVersion: string; minorVersion: string } = + let apiVersion: { majorVersion: number; minorVersion: number } = await this.sendCommand("start", {}); + if ( + apiVersion.majorVersion != this.supportedManualControlMajorVersion || + apiVersion.minorVersion < this.supportedManualControlMinorVersion + ) { + throw new Error( + `API Version ${apiVersion.majorVersion}.${apiVersion.minorVersion} is not supported`, + ); + } + this.moduleAddress = await this.sendCommand("getModuleAddress", { serialNumber: "Embedded", moduleAddress: 173, diff --git a/packages/sample/src/command/servo.ts b/packages/sample/src/command/servo.ts index a4a92597..2bfadf09 100644 --- a/packages/sample/src/command/servo.ts +++ b/packages/sample/src/command/servo.ts @@ -4,4 +4,5 @@ export async function runServo(hub: ExpansionHub, channel: number, pulseWidth: n await hub.setServoConfiguration(channel, framePeriod); await hub.setServoPulseWidth(channel, pulseWidth); await hub.setServoEnable(channel, true); + hub.close(); } From 749333dddefc684eeb59b932af7ec6d170448196 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 9 Jun 2023 13:19:39 -0500 Subject: [PATCH 31/81] make compatible with latest control hub changes --- package-lock.json | 23 ++++++++----------- .../control-hub/src/internal/ControlHub.ts | 8 ++++--- packages/rhsplib/package.json | 3 ++- packages/sample/src/adb-setup.ts | 2 +- packages/sample/src/command/servo.ts | 4 +++- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/package-lock.json b/package-lock.json index 66614306..94400d63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3,7 +3,6 @@ "lockfileVersion": 2, "requires": true, "packages": { - "packages": {}, "": { "name": "root", "workspaces": [ @@ -5310,6 +5309,11 @@ "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node_modules/node-fetch": { "version": "2.6.9", "dev": true, @@ -7830,11 +7834,6 @@ "typescript": "^5.0.2" } }, - "packages/rhsplib/node_modules/node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" - }, "packages/sample": { "name": "rev-hub-cli", "version": "1.0.0", @@ -9187,13 +9186,6 @@ "node-gyp-build": "^4.6.0", "prebuildify": "^5.0.1", "typescript": "^5.0.2" - }, - "dependencies": { - "node-addon-api": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", - "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" - } } }, "@serialport/binding-mock": { @@ -11438,6 +11430,11 @@ "semver": "^7.3.5" } }, + "node-addon-api": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" + }, "node-fetch": { "version": "2.6.9", "dev": true, diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 0a608f23..b504cb2e 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -53,11 +53,12 @@ export class ControlHubInternal implements ControlHub { } isParent(): this is ParentRevHub { - return this.serialNumber !== undefined; + return true; } async open(ip: string = "192.168.43.1", port: string = "8081"): Promise { this.webSocketConnection = new WebSocket(`ws://${ip}:${port}`); + console.log(`Opening on port ${port}`); this.webSocketConnection.on("message", (data) => { let rawMessage = JSON.parse(data.toString()); @@ -104,7 +105,7 @@ export class ControlHubInternal implements ControlHub { } this.moduleAddress = await this.sendCommand("getModuleAddress", { - serialNumber: "Embedded", + serialNumber: "(embedded)", moduleAddress: 173, }); resolve(); @@ -690,7 +691,7 @@ export class ControlHubInternal implements ControlHub { async sendCommand(type: string, params: P, timeout: number = 1000): Promise { let key = 0; let messagePayload = { - key: key, + commandKey: key, commandPayload: JSON.stringify(params), }; let payload = { @@ -706,6 +707,7 @@ export class ControlHubInternal implements ControlHub { if (response !== undefined) { resolve(response); } else { + console.error(`Got error for ${type}`); let e = new Error(); Object.assign(e, error); reject(e); diff --git a/packages/rhsplib/package.json b/packages/rhsplib/package.json index 9eb02fc4..d3a21bb4 100644 --- a/packages/rhsplib/package.json +++ b/packages/rhsplib/package.json @@ -24,7 +24,8 @@ }, "scripts": { "build": "tsc", - "install": "node-gyp-build \"node scripts/build-RHSPlib.mjs\"", + "install": "", + "postinstall": "node-gyp-build \"node scripts/build-RHSPlib.mjs\"", "prepublishOnly": "prebuildify --napi && tsc" }, "gypfile": true diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index 61db9ef3..317fe96b 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -15,7 +15,7 @@ export async function openUsbControlHubs(): Promise { let port = await configureHubTcp(deviceClient); let serialNumber = device.id; - let hub = await openControlHub(serialNumber, port); + let hub = await openControlHub("(embedded)", port); controlHubs.push(hub); } } diff --git a/packages/sample/src/command/servo.ts b/packages/sample/src/command/servo.ts index 2bfadf09..8c90d1be 100644 --- a/packages/sample/src/command/servo.ts +++ b/packages/sample/src/command/servo.ts @@ -4,5 +4,7 @@ export async function runServo(hub: ExpansionHub, channel: number, pulseWidth: n await hub.setServoConfiguration(channel, framePeriod); await hub.setServoPulseWidth(channel, pulseWidth); await hub.setServoEnable(channel, true); - hub.close(); + setTimeout(() => { + hub.close(); + }, 10000); } From 734f65a313ccbbb7ba1d73f6932f7fabcbfec7b8 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 9 Jun 2023 14:25:36 -0500 Subject: [PATCH 32/81] use new id system for control hubs --- .../control-hub/src/internal/ControlHub.ts | 269 ++++++++---------- 1 file changed, 124 insertions(+), 145 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index b504cb2e..811cc57c 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -33,6 +33,9 @@ export class ControlHubInternal implements ControlHub { readonly serialNumber: string; readonly children: ReadonlyArray = []; + private id: string | null; + private keyGenerator = 0; + private supportedManualControlMajorVersion = 0; private supportedManualControlMinorVersion = 1; @@ -42,14 +45,24 @@ export class ControlHubInternal implements ControlHub { isConnected = false; private webSocketConnection!: WebSocket; - private keyGenerator = 0; private currentActiveCommands = new Map< any, (response: any | undefined, error: any | undefined) => void >(); - constructor(serialNumber: string) { + constructor(serialNumber: string, id: string | null = null) { this.serialNumber = serialNumber; + this.id = id; + } + + setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { + throw new Error("Method not implemented."); + } + setAllDigitalOutputs(bitPackedField: number): Promise { + throw new Error("Method not implemented."); + } + getDigitalInput(digitalChannel: number): Promise { + throw new Error("Method not implemented."); } isParent(): this is ParentRevHub { @@ -139,46 +152,99 @@ export class ControlHubInternal implements ControlHub { }); } - getADC(): Promise { - return Promise.resolve(0); + async getAnalogInput(channel: number): Promise { + return await this.sendCommand("getAnalogInput", { + id: this.id, + channel: channel, + }); + } + + async get5VBusVoltage(): Promise { + return await this.sendCommand("get5VBusVoltage", { + id: this.id, + }); + } + + async getBatteryCurrent(): Promise { + return await this.sendCommand("getBatteryCurrent", { + id: this.id, + }); + } + + async getBatteryVoltage(): Promise { + return await this.sendCommand("getBatteryVoltage", { + id: this.id, + }); + } + + async getDigitalBusCurrent(): Promise { + return await this.sendCommand("getDigitalBusCurrent", { + id: this.id, + }); + } + + async getI2CCurrent(): Promise { + return await this.sendCommand("getI2CCurrent", { + id: this.id, + }); + } + + async getMotorCurrent(motorChannel: number): Promise { + return await this.sendCommand("getMotorCurrent", { + id: this.id, + }); + } + + async getServoCurrent(): Promise { + return await this.sendCommand("getMotorCurrent", { + id: this.id, + }); + } + + async getTemperature(): Promise { + return await this.sendCommand("getTemperature", { + id: this.id, + }); } async getBulkInputData(): Promise { - let result = await this.sendCommand("getBulkInputData", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + return await this.sendCommand("getBulkInputData", { + id: this.id, }); throw new Error("not implemented"); } async getDigitalAllInputs(): Promise { return await this.sendCommand("getAllDigitalInputs", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } async getDigitalDirection(dioPin: number): Promise { let isOutput = await this.sendCommand("getDigitalDirection", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, channel: dioPin, }); return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; } + async getDigitalSingleInput(dioPin: number): Promise { + return await this.sendCommand("getDigitalInput", { + id: this.id, + channel: dioPin, + }); + } + async getFTDIResetControl(): Promise { return await this.sendCommand("getFtdiResetControl", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } async getI2CChannelConfiguration(i2cChannel: number): Promise { let speedCode = await this.sendCommand("getI2CChannelConfiguration", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, channel: i2cChannel, }); @@ -200,8 +266,7 @@ export class ControlHubInternal implements ControlHub { functionNumber: number, ): Promise { return await this.sendCommand("getInterfacePacketId", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, interfaceName: interfaceName, functionNumber: functionNumber, }); @@ -229,30 +294,26 @@ export class ControlHubInternal implements ControlHub { async getModuleStatus(clearStatusAfterResponse: boolean): Promise { return await this.sendCommand("getModuleStatus", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } async getMotorAtTarget(motorChannel: number): Promise { return await this.sendCommand("getIsMotorAtTarget", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { return await this.sendCommand("getMotorAlertLevel", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } async getMotorChannelEnable(motorChannel: number): Promise { return await this.sendCommand("getMotorChannelEnable", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } @@ -261,24 +322,21 @@ export class ControlHubInternal implements ControlHub { motorChannel: number, ): Promise<{ motorMode: number; floatAtZero: boolean }> { return await this.sendCommand("getMotorMode", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } async getMotorConstantPower(motorChannel: number): Promise { return await this.sendCommand("getMotorConstantPower", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } async getMotorEncoderPosition(motorChannel: number): Promise { return await this.sendCommand("getMotorEncoderPosition", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } @@ -323,47 +381,41 @@ export class ControlHubInternal implements ControlHub { async getMotorTargetVelocity(motorChannel: number): Promise { return await this.sendCommand("getMotorTargetVelocity", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } async getPhoneChargeControl(): Promise { return await this.sendCommand("getPhoneChargeControl", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } async getServoConfiguration(servoChannel: number): Promise { return await this.sendCommand("getServoConfiguration", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, servoChannel: servoChannel, }); } async getServoEnable(servoChannel: number): Promise { return await this.sendCommand("getServoEnable", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, servoChannel: servoChannel, }); } async getServoPulseWidth(servoChannel: number): Promise { return await this.sendCommand("getServoPulseWidth", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, servoChannel: servoChannel, }); } async injectDataLogHint(hintText: string): Promise { await this.sendCommand("injectDebugLogHint", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, hint: hintText, }); } @@ -411,23 +463,20 @@ export class ControlHubInternal implements ControlHub { async readVersionString(): Promise { return await this.sendCommand("readVersionString", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } async resetMotorEncoder(motorChannel: number): Promise { await this.sendCommand("resetMotorEncoder", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, }); } async sendFailSafe(): Promise { await this.sendCommand("readVersionString", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } @@ -446,8 +495,7 @@ export class ControlHubInternal implements ControlHub { verbosityLevel: VerbosityLevel, ): Promise { await this.sendCommand("readVersionString", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, debugGroup: debugGroup, verbosityLevel: verbosityLevel, }); @@ -455,16 +503,14 @@ export class ControlHubInternal implements ControlHub { async setDigitalAllOutputs(bitPackedField: number): Promise { await this.sendCommand("readVersionString", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, bitField: bitPackedField, }); } async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { await this.sendCommand("readVersionString", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, pin: dioPin, isOutput: direction == DigitalChannelDirection.Output, }); @@ -472,8 +518,7 @@ export class ControlHubInternal implements ControlHub { async setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { await this.sendCommand("readVersionString", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, pin: dioPin, value: value ?? false, }); @@ -481,8 +526,7 @@ export class ControlHubInternal implements ControlHub { async setFTDIResetControl(ftdiResetControl: boolean): Promise { await this.sendCommand("setFtdiResetControl", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, }); } @@ -491,8 +535,7 @@ export class ControlHubInternal implements ControlHub { speedCode: I2CSpeedCode, ): Promise { await this.sendCommand("setI2CChannelConfiguration", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, i2cChannel: i2cChannel, speedCode: speedCode, }); @@ -500,8 +543,7 @@ export class ControlHubInternal implements ControlHub { async setModuleLedColor(red: number, green: number, blue: number): Promise { await this.sendCommand("setLedColor", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, r: red, g: green, b: blue, @@ -509,9 +551,8 @@ export class ControlHubInternal implements ControlHub { } async setModuleLedPattern(ledPattern: LedPattern): Promise { - await this.sendCommand("setLedColor", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + await this.sendCommand("setLedPattern", { + id: this.id, rgbtPatternStep0: ledPattern.rgbtPatternStep0, rgbtPatternStep1: ledPattern.rgbtPatternStep1, rgbtPatternStep2: ledPattern.rgbtPatternStep2, @@ -536,8 +577,7 @@ export class ControlHubInternal implements ControlHub { currentLimit_mA: number, ): Promise { await this.sendCommand("setMotorAlertLevel", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, currentLimit_mA: currentLimit_mA, }); @@ -545,8 +585,7 @@ export class ControlHubInternal implements ControlHub { async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { await this.sendCommand("setMotorEnabled", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, enable: enable, }); @@ -558,8 +597,7 @@ export class ControlHubInternal implements ControlHub { floatAtZero: boolean, ): Promise { await this.sendCommand("setMotorChannelMode", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, motorMode: motorMode, floatAtZero: floatAtZero, @@ -568,8 +606,7 @@ export class ControlHubInternal implements ControlHub { async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { await this.sendCommand("setMotorConstantPower", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, motorPower: powerLevel, }); @@ -581,8 +618,7 @@ export class ControlHubInternal implements ControlHub { pid: PidCoefficients, ): Promise { await this.sendCommand("setMotorPidCoefficients", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, motorMode: motorMode, p: pid.p, @@ -597,8 +633,7 @@ export class ControlHubInternal implements ControlHub { targetTolerance_counts: number, ): Promise { await this.sendCommand("setMotorTargetPosition", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, targetPositionCounts: targetPosition_counts, targetToleranceCounts: targetTolerance_counts, @@ -610,8 +645,7 @@ export class ControlHubInternal implements ControlHub { velocity_cps: number, ): Promise { await this.sendCommand("setMotorTargetVelocity", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, motorChannel: motorChannel, velocityCps: velocity_cps, }); @@ -619,16 +653,14 @@ export class ControlHubInternal implements ControlHub { async setNewModuleAddress(newModuleAddress: number): Promise { await this.sendCommand("setNewModuleAddress", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, address: newModuleAddress, }); } async setPhoneChargeControl(chargeEnable: boolean): Promise { await this.sendCommand("setPhoneChargeControl", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, enabled: chargeEnable, }); } @@ -638,8 +670,7 @@ export class ControlHubInternal implements ControlHub { framePeriod: number, ): Promise { await this.sendCommand("setServoConfiguration", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, servoChannel: servoChannel, framePeriod: framePeriod, }); @@ -647,8 +678,7 @@ export class ControlHubInternal implements ControlHub { async setServoEnable(servoChannel: number, enable: boolean): Promise { await this.sendCommand("setServoEnable", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, servoChannel: servoChannel, enabled: enable, }); @@ -656,8 +686,7 @@ export class ControlHubInternal implements ControlHub { async setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { await this.sendCommand("setServoPulseWidth", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + id: this.id, servoChannel: servoChannel, pulseWidth: pulseWidth, }); @@ -689,7 +718,7 @@ export class ControlHubInternal implements ControlHub { } async sendCommand(type: string, params: P, timeout: number = 1000): Promise { - let key = 0; + let key = this.keyGenerator++; let messagePayload = { commandKey: key, commandPayload: JSON.stringify(params), @@ -727,74 +756,24 @@ export class ControlHubInternal implements ControlHub { }); } - addChild(hub: RevHub): void { + async addChild(hub: RevHub): Promise { throw new Error("not implemented"); } - addChildByAddress(moduleAddress: number): Promise { - throw new Error("not implemented"); - } + async addChildByAddress(moduleAddress: number): Promise { + let id: string = await this.sendCommand("addChild", moduleAddress); - get5VBusVoltage(): Promise { - return Promise.resolve(0); + return new ControlHubInternal("(embedded)", id); } getAllDigitalInputs(): Promise { return Promise.resolve(0); } - getAnalogInput(channel: number): Promise { - return Promise.resolve(0); - } - - getBatteryCurrent(): Promise { - return Promise.resolve(0); - } - - getBatteryVoltage(): Promise { - return Promise.resolve(0); - } - - getDigitalBusCurrent(): Promise { - return Promise.resolve(0); - } - - async getDigitalInput(digitalChannel: number): Promise { - return await this.sendCommand("getDigitalInput", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - channel: digitalChannel, - }); - } - - getI2CCurrent(): Promise { - return Promise.resolve(0); - } - getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { return this.getMotorPIDCoefficients(motorChannel, motorMode); } - getMotorCurrent(motorChannel: number): Promise { - return Promise.resolve(0); - } - - getServoCurrent(): Promise { - return Promise.resolve(0); - } - - getTemperature(): Promise { - return Promise.resolve(0); - } - - setAllDigitalOutputs(bitPackedField: number): Promise { - return Promise.resolve(undefined); - } - - setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { - return Promise.resolve(undefined); - } - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid, pid: PidCoefficients): Promise; setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; From b28fef916bc761b62a9dad17035441a697a09e82 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 9 Jun 2023 14:55:45 -0500 Subject: [PATCH 33/81] update to latest changes in control hub --- packages/control-hub/src/discovery.ts | 2 +- packages/control-hub/src/index.ts | 3 ++- packages/control-hub/src/internal/ControlHub.ts | 13 +++++++++---- packages/sample/src/adb-setup.ts | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index bb85d757..5a5078d3 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -10,7 +10,7 @@ export async function openConnectedControlHub(): Promise } async function createWiFiControlHub(): Promise { - let hub = new ControlHubInternal("Placeholder"); + let hub = new ControlHubInternal("Placeholder", 173); if (!(await hub.isWiFiConnected())) { throw new Error("Hub is not connected via WiFi"); diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index 14bf7881..6337ac9d 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -5,9 +5,10 @@ export { openConnectedControlHub } from "./discovery.js"; export async function openControlHub( serialNumber: string, + moduleAddress: number, port: number, ): Promise { - let hub = new ControlHubInternal(serialNumber); + let hub = new ControlHubInternal(serialNumber, moduleAddress); await hub.open("127.0.0.1", (port + 1).toString()); return hub; } diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 811cc57c..bb317396 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -33,7 +33,7 @@ export class ControlHubInternal implements ControlHub { readonly serialNumber: string; readonly children: ReadonlyArray = []; - private id: string | null; + private id: any | null; private keyGenerator = 0; private supportedManualControlMajorVersion = 0; @@ -50,8 +50,9 @@ export class ControlHubInternal implements ControlHub { (response: any | undefined, error: any | undefined) => void >(); - constructor(serialNumber: string, id: string | null = null) { + constructor(serialNumber: string, moduleAddress: number, id: any | null = null) { this.serialNumber = serialNumber; + this.moduleAddress = moduleAddress; this.id = id; } @@ -105,6 +106,10 @@ export class ControlHubInternal implements ControlHub { return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { this.isConnected = true; + this.id = await this.sendCommand("openHub", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }); let apiVersion: { majorVersion: number; minorVersion: number } = await this.sendCommand("start", {}); @@ -761,9 +766,9 @@ export class ControlHubInternal implements ControlHub { } async addChildByAddress(moduleAddress: number): Promise { - let id: string = await this.sendCommand("addChild", moduleAddress); + let id: any = await this.sendCommand("addChild", moduleAddress); - return new ControlHubInternal("(embedded)", id); + return new ControlHubInternal("(embedded)", moduleAddress, id); } getAllDigitalInputs(): Promise { diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index 317fe96b..e11583fd 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -15,7 +15,7 @@ export async function openUsbControlHubs(): Promise { let port = await configureHubTcp(deviceClient); let serialNumber = device.id; - let hub = await openControlHub("(embedded)", port); + let hub = await openControlHub("(embedded)", 173, port); controlHubs.push(hub); } } From d38a57861fe58fc903146b90785d9e0a6df865a1 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 15 Jun 2023 12:27:56 -0500 Subject: [PATCH 34/81] Properly handle children hierarchy on Control Hub --- packages/control-hub/src/discovery.ts | 2 +- packages/control-hub/src/index.ts | 3 +- .../control-hub/src/internal/ControlHub.ts | 567 +++++++--------- .../src/internal/ControlHubConnected.ts | 641 ++++++++++++++++++ packages/core/src/ControlHub.ts | 7 +- packages/sample/src/HubStringify.ts | 23 +- packages/sample/src/adb-setup.ts | 2 +- packages/sample/src/command/list.ts | 16 +- tsconfig.json | 1 + 9 files changed, 900 insertions(+), 362 deletions(-) create mode 100644 packages/control-hub/src/internal/ControlHubConnected.ts diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts index 5a5078d3..bb85d757 100644 --- a/packages/control-hub/src/discovery.ts +++ b/packages/control-hub/src/discovery.ts @@ -10,7 +10,7 @@ export async function openConnectedControlHub(): Promise } async function createWiFiControlHub(): Promise { - let hub = new ControlHubInternal("Placeholder", 173); + let hub = new ControlHubInternal("Placeholder"); if (!(await hub.isWiFiConnected())) { throw new Error("Hub is not connected via WiFi"); diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index 6337ac9d..3ac46878 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -2,13 +2,14 @@ import { ControlHubInternal } from "./internal/ControlHub.js"; import { ControlHub } from "@rev-robotics/rev-hub-core"; export { openConnectedControlHub } from "./discovery.js"; +export { openUsbControlHubsAndChildren } from "./internal/ControlHub.js"; export async function openControlHub( serialNumber: string, moduleAddress: number, port: number, ): Promise { - let hub = new ControlHubInternal(serialNumber, moduleAddress); + let hub = new ControlHubInternal(serialNumber); await hub.open("127.0.0.1", (port + 1).toString()); return hub; } diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index bb317396..67729e3e 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -2,36 +2,49 @@ import axios from "axios"; import semver from "semver"; import WebSocket from "isomorphic-ws"; import { - ControlHub, - ExpansionHub, - ParentRevHub, - RevHub, - RevHubType, - TimeoutError, BulkInputData, + ControlHub, ClosedLoopControlAlgorithm, - DebugGroup, DigitalChannelDirection, DigitalState, + DebugGroup, + ExpansionHub, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, LedPattern, ModuleInterface, - ModuleStatus, MotorMode, - PidCoefficients, PidfCoefficients, + ModuleStatus, + ParentRevHub, + PidCoefficients, + RevHub, + RevHubType, Rgb, + TimeoutError, + MotorMode, + PidfCoefficients, VerbosityLevel, Version, } from "@rev-robotics/rev-hub-core"; +import { openUsbControlHubs } from "rev-hub-cli/dist/adb-setup.js"; import { clearTimeout } from "timers"; +import { ControlHubConnected } from "./ControlHubConnected.js"; export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; - moduleAddress: number = 0; + readonly moduleAddress: number = 173; responseTimeoutMs: number = 0; type: RevHubType = RevHubType.ControlHub; readonly serialNumber: string; - readonly children: ReadonlyArray = []; + + /** + * All children connected over USB, as well as the one embedded hub. + */ + readonly children: RevHub[] = []; + + /** + * All children connected over USB. + */ + readonly usbChildren: RevHub[] = []; private id: any | null; private keyGenerator = 0; @@ -44,16 +57,20 @@ export class ControlHubInternal implements ControlHub { */ isConnected = false; + /** + * The board for this control hub. All Expansion Hub commands go through + * this delegate. + */ + private embedded!: ControlHubConnected; + private webSocketConnection!: WebSocket; private currentActiveCommands = new Map< any, (response: any | undefined, error: any | undefined) => void >(); - constructor(serialNumber: string, moduleAddress: number, id: any | null = null) { + constructor(serialNumber: string) { this.serialNumber = serialNumber; - this.moduleAddress = moduleAddress; - this.id = id; } setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { @@ -106,26 +123,34 @@ export class ControlHubInternal implements ControlHub { return new Promise((resolve, reject) => { this.webSocketConnection.on("open", async () => { this.isConnected = true; - this.id = await this.sendCommand("openHub", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - }); + await this.subscribe(); let apiVersion: { majorVersion: number; minorVersion: number } = await this.sendCommand("start", {}); + this.id = await this.openHub("(embedded)", this.moduleAddress); + + this.embedded = new ControlHubConnected( + true, + RevHubType.ControlHub, + this.sendCommand, + "(embedded)", + this.moduleAddress, + this.id, + ); + + this.children.push(this.embedded); + if ( - apiVersion.majorVersion != this.supportedManualControlMajorVersion || + apiVersion.majorVersion !== this.supportedManualControlMajorVersion || apiVersion.minorVersion < this.supportedManualControlMinorVersion ) { - throw new Error( - `API Version ${apiVersion.majorVersion}.${apiVersion.minorVersion} is not supported`, + reject( + new Error( + `API Version ${apiVersion.majorVersion}.${apiVersion.minorVersion} is not supported`, + ), ); } - this.moduleAddress = await this.sendCommand("getModuleAddress", { - serialNumber: "(embedded)", - moduleAddress: 173, - }); resolve(); }); }); @@ -151,278 +176,180 @@ export class ControlHubInternal implements ControlHub { return path.includes("_box") && path.includes("msm8916_64"); } - close(): void { - this.sendCommand("stop", {}).then(() => { - this.webSocketConnection.close(); + async subscribe(): Promise { + let payload = { + namespace: "system", + type: "subscribeToNamespace", + payload: "MC", + }; + this.webSocketConnection.send(JSON.stringify(payload)); + } + + async openHub( + serialNumber: string, + parentAddress: number, + address: number = parentAddress, + ): Promise { + return await this.sendCommand("openHub", { + parentSerialNumber: serialNumber, + parentHubAddress: parentAddress, + hubAddress: address, }); } + close() { + this.embedded.close(); + this.webSocketConnection.close(); + } + async getAnalogInput(channel: number): Promise { - return await this.sendCommand("getAnalogInput", { - id: this.id, - channel: channel, - }); + return this.embedded.getAnalogInput(channel); } async get5VBusVoltage(): Promise { - return await this.sendCommand("get5VBusVoltage", { - id: this.id, - }); + return this.embedded.get5VBusVoltage(); } async getBatteryCurrent(): Promise { - return await this.sendCommand("getBatteryCurrent", { - id: this.id, - }); + return this.embedded.getBatteryCurrent(); } async getBatteryVoltage(): Promise { - return await this.sendCommand("getBatteryVoltage", { - id: this.id, - }); + return this.embedded.getBatteryVoltage(); } async getDigitalBusCurrent(): Promise { - return await this.sendCommand("getDigitalBusCurrent", { - id: this.id, - }); + return this.embedded.getDigitalBusCurrent(); } async getI2CCurrent(): Promise { - return await this.sendCommand("getI2CCurrent", { - id: this.id, - }); + return this.embedded.getI2CCurrent(); } async getMotorCurrent(motorChannel: number): Promise { - return await this.sendCommand("getMotorCurrent", { - id: this.id, - }); + return this.embedded.getMotorCurrent(motorChannel); } async getServoCurrent(): Promise { - return await this.sendCommand("getMotorCurrent", { - id: this.id, - }); + return this.embedded.getServoCurrent(); } async getTemperature(): Promise { - return await this.sendCommand("getTemperature", { - id: this.id, - }); + return this.embedded.getTemperature(); } async getBulkInputData(): Promise { - return await this.sendCommand("getBulkInputData", { - id: this.id, - }); - throw new Error("not implemented"); + return this.embedded.getBulkInputData(); } async getDigitalAllInputs(): Promise { - return await this.sendCommand("getAllDigitalInputs", { - id: this.id, - }); + return this.embedded.getDigitalAllInputs(); } async getDigitalDirection(dioPin: number): Promise { - let isOutput = await this.sendCommand("getDigitalDirection", { - id: this.id, - channel: dioPin, - }); - - return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; + return this.embedded.getDigitalDirection(dioPin); } async getDigitalSingleInput(dioPin: number): Promise { - return await this.sendCommand("getDigitalInput", { - id: this.id, - channel: dioPin, - }); + return this.embedded.getDigitalSingleInput(dioPin); } async getFTDIResetControl(): Promise { - return await this.sendCommand("getFtdiResetControl", { - id: this.id, - }); + return this.embedded.getFTDIResetControl(); } async getI2CChannelConfiguration(i2cChannel: number): Promise { - let speedCode = await this.sendCommand("getI2CChannelConfiguration", { - id: this.id, - channel: i2cChannel, - }); - - return speedCode == 1 - ? I2CSpeedCode.SpeedCode400_Kbps - : I2CSpeedCode.SpeedCode100_Kbps; + return this.embedded.getI2CChannelConfiguration(i2cChannel); } getI2CReadStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); + return this.embedded.getI2CReadStatus(i2cChannel); } getI2CWriteStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); + return this.embedded.getI2CWriteStatus(i2cChannel); } async getInterfacePacketID( interfaceName: string, functionNumber: number, ): Promise { - return await this.sendCommand("getInterfacePacketId", { - id: this.id, - interfaceName: interfaceName, - functionNumber: functionNumber, - }); + return this.embedded.getInterfacePacketID(interfaceName, functionNumber); } async getModuleLedColor(): Promise { - let result: { r: number; g: number; b: number } = await this.sendCommand( - "getLedColor", - { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - }, - ); - - return { - red: result.r, - green: result.g, - blue: result.b, - }; + return this.embedded.getModuleLedColor(); } getModuleLedPattern(): Promise { - throw new Error("not implemented"); + return this.embedded.getModuleLedPattern(); } async getModuleStatus(clearStatusAfterResponse: boolean): Promise { - return await this.sendCommand("getModuleStatus", { - id: this.id, - }); + return this.embedded.getModuleStatus(clearStatusAfterResponse); } async getMotorAtTarget(motorChannel: number): Promise { - return await this.sendCommand("getIsMotorAtTarget", { - id: this.id, - }); + return this.embedded.getMotorAtTarget(motorChannel); } async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { - return await this.sendCommand("getMotorAlertLevel", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.getMotorChannelCurrentAlertLevel(motorChannel); } async getMotorChannelEnable(motorChannel: number): Promise { - return await this.sendCommand("getMotorChannelEnable", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.getMotorChannelEnable(motorChannel); } async getMotorChannelMode( motorChannel: number, ): Promise<{ motorMode: number; floatAtZero: boolean }> { - return await this.sendCommand("getMotorMode", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.getMotorChannelMode(motorChannel); } async getMotorConstantPower(motorChannel: number): Promise { - return await this.sendCommand("getMotorConstantPower", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.getMotorConstantPower(motorChannel); } async getMotorEncoderPosition(motorChannel: number): Promise { - return await this.sendCommand("getMotorEncoderPosition", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.getMotorEncoderPosition(motorChannel); } async getMotorPIDCoefficients( motorChannel: number, motorMode: number, ): Promise { - let result: { p: number; i: number; d: number } = await this.sendCommand( - "getMotorPidCoefficients", - { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - motorChannel: motorChannel, - motorMode: motorMode, - }, - ); - - return { - p: result.p, - i: result.i, - d: result.d, - algorithm: ClosedLoopControlAlgorithm.Pid - }; + return this.embedded.getMotorPIDCoefficients(motorChannel, motorMode); } async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { - let result: { targetPositionCounts: number; targetToleranceCounts: number } = - await this.sendCommand("getMotorTargetPosition", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - motorChannel: motorChannel, - }); - - return { - targetPosition: result.targetPositionCounts, - targetTolerance: result.targetToleranceCounts, - }; + return this.embedded.getMotorTargetPosition(motorChannel); } async getMotorTargetVelocity(motorChannel: number): Promise { - return await this.sendCommand("getMotorTargetVelocity", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.getMotorTargetVelocity(motorChannel); } async getPhoneChargeControl(): Promise { - return await this.sendCommand("getPhoneChargeControl", { - id: this.id, - }); + return this.embedded.getPhoneChargeControl(); } async getServoConfiguration(servoChannel: number): Promise { - return await this.sendCommand("getServoConfiguration", { - id: this.id, - servoChannel: servoChannel, - }); + return this.embedded.getServoConfiguration(servoChannel); } async getServoEnable(servoChannel: number): Promise { - return await this.sendCommand("getServoEnable", { - id: this.id, - servoChannel: servoChannel, - }); + return this.embedded.getServoEnable(servoChannel); } async getServoPulseWidth(servoChannel: number): Promise { - return await this.sendCommand("getServoPulseWidth", { - id: this.id, - servoChannel: servoChannel, - }); + return this.embedded.getServoPulseWidth(servoChannel); } async injectDataLogHint(hintText: string): Promise { - await this.sendCommand("injectDebugLogHint", { - id: this.id, - hint: hintText, - }); + return this.embedded.injectDataLogHint(hintText); } isExpansionHub(): this is ExpansionHub { @@ -430,22 +357,11 @@ export class ControlHubInternal implements ControlHub { } on(eventName: "error", listener: (error: Error) => void): RevHub { - throw new Error("not implemented"); + return this.embedded.on(eventName, listener); } async queryInterface(interfaceName: string): Promise { - let result: { name: string; firstPacketId: number; numberIds: number } = - await this.sendCommand("queryInterface", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - interfaceName: interfaceName, - }); - - return { - name: result.name, - firstPacketID: result.firstPacketId, - numberIDValues: result.numberIds, - }; + return this.embedded.queryInterface(interfaceName); } readI2CMultipleBytes( @@ -453,147 +369,95 @@ export class ControlHubInternal implements ControlHub { slaveAddress: number, numBytesToRead: number, ): Promise { - throw new Error("not implemented"); + return this.embedded.readI2CMultipleBytes( + i2cChannel, + slaveAddress, + numBytesToRead, + ); } readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { - throw new Error("not implemented"); + return this.embedded.readI2CSingleByte(i2cChannel, slaveAddress); } async readVersion(): Promise { - let versionString = await this.readVersionString(); - //ToDo(landry) parse version string - throw new Error("not implemented"); + return this.embedded.readVersion(); } async readVersionString(): Promise { - return await this.sendCommand("readVersionString", { - id: this.id, - }); + return this.embedded.readVersionString(); } async resetMotorEncoder(motorChannel: number): Promise { - await this.sendCommand("resetMotorEncoder", { - id: this.id, - motorChannel: motorChannel, - }); + return this.embedded.resetMotorEncoder(motorChannel); } async sendFailSafe(): Promise { - await this.sendCommand("readVersionString", { - id: this.id, - }); + return this.embedded.sendFailSafe(); } - async sendKeepAlive(): Promise {} + async sendKeepAlive(): Promise { + return this.embedded.sendKeepAlive(); + } async sendReadCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); + return this.embedded.sendReadCommand(packetTypeID, payload); } sendWriteCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); + return this.embedded.sendWriteCommand(packetTypeID, payload); } async setDebugLogLevel( debugGroup: DebugGroup, verbosityLevel: VerbosityLevel, ): Promise { - await this.sendCommand("readVersionString", { - id: this.id, - debugGroup: debugGroup, - verbosityLevel: verbosityLevel, - }); + return this.embedded.setDebugLogLevel(debugGroup, verbosityLevel); } async setDigitalAllOutputs(bitPackedField: number): Promise { - await this.sendCommand("readVersionString", { - id: this.id, - bitField: bitPackedField, - }); + return this.embedded.setDigitalAllOutputs(bitPackedField); } async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { - await this.sendCommand("readVersionString", { - id: this.id, - pin: dioPin, - isOutput: direction == DigitalChannelDirection.Output, - }); + return this.embedded.setDigitalDirection(dioPin, direction); } async setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { - await this.sendCommand("readVersionString", { - id: this.id, - pin: dioPin, - value: value ?? false, - }); + return this.embedded.setDigitalSingleOutput(dioPin, value); } async setFTDIResetControl(ftdiResetControl: boolean): Promise { - await this.sendCommand("setFtdiResetControl", { - id: this.id, - }); + return this.embedded.setFTDIResetControl(ftdiResetControl); } async setI2CChannelConfiguration( i2cChannel: number, speedCode: I2CSpeedCode, ): Promise { - await this.sendCommand("setI2CChannelConfiguration", { - id: this.id, - i2cChannel: i2cChannel, - speedCode: speedCode, - }); + return this.embedded.setI2CChannelConfiguration(i2cChannel, speedCode); } async setModuleLedColor(red: number, green: number, blue: number): Promise { - await this.sendCommand("setLedColor", { - id: this.id, - r: red, - g: green, - b: blue, - }); + return this.embedded.setModuleLedColor(red, green, blue); } async setModuleLedPattern(ledPattern: LedPattern): Promise { - await this.sendCommand("setLedPattern", { - id: this.id, - rgbtPatternStep0: ledPattern.rgbtPatternStep0, - rgbtPatternStep1: ledPattern.rgbtPatternStep1, - rgbtPatternStep2: ledPattern.rgbtPatternStep2, - rgbtPatternStep3: ledPattern.rgbtPatternStep3, - rgbtPatternStep4: ledPattern.rgbtPatternStep4, - rgbtPatternStep5: ledPattern.rgbtPatternStep5, - rgbtPatternStep6: ledPattern.rgbtPatternStep6, - rgbtPatternStep7: ledPattern.rgbtPatternStep7, - rgbtPatternStep8: ledPattern.rgbtPatternStep8, - rgbtPatternStep9: ledPattern.rgbtPatternStep9, - rgbtPatternStep10: ledPattern.rgbtPatternStep10, - rgbtPatternStep11: ledPattern.rgbtPatternStep11, - rgbtPatternStep12: ledPattern.rgbtPatternStep12, - rgbtPatternStep13: ledPattern.rgbtPatternStep13, - rgbtPatternStep14: ledPattern.rgbtPatternStep14, - rgbtPatternStep15: ledPattern.rgbtPatternStep15, - }); + return this.embedded.setModuleLedPattern(ledPattern); } async setMotorChannelCurrentAlertLevel( motorChannel: number, currentLimit_mA: number, ): Promise { - await this.sendCommand("setMotorAlertLevel", { - id: this.id, - motorChannel: motorChannel, - currentLimit_mA: currentLimit_mA, - }); + return this.embedded.setMotorChannelCurrentAlertLevel( + motorChannel, + currentLimit_mA, + ); } async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { - await this.sendCommand("setMotorEnabled", { - id: this.id, - motorChannel: motorChannel, - enable: enable, - }); + return this.embedded.setMotorChannelEnable(motorChannel, enable); } async setMotorChannelMode( @@ -601,20 +465,11 @@ export class ControlHubInternal implements ControlHub { motorMode: number, floatAtZero: boolean, ): Promise { - await this.sendCommand("setMotorChannelMode", { - id: this.id, - motorChannel: motorChannel, - motorMode: motorMode, - floatAtZero: floatAtZero, - }); + return this.embedded.setMotorChannelMode(motorChannel, motorMode, floatAtZero); } async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { - await this.sendCommand("setMotorConstantPower", { - id: this.id, - motorChannel: motorChannel, - motorPower: powerLevel, - }); + return this.embedded.setMotorConstantPower(motorChannel, powerLevel); } async setMotorPIDCoefficients( @@ -622,14 +477,7 @@ export class ControlHubInternal implements ControlHub { motorMode: number, pid: PidCoefficients, ): Promise { - await this.sendCommand("setMotorPidCoefficients", { - id: this.id, - motorChannel: motorChannel, - motorMode: motorMode, - p: pid.p, - i: pid.i, - d: pid.d, - }); + return this.embedded.setMotorPIDCoefficients(motorChannel, motorMode, pid); } async setMotorTargetPosition( @@ -637,64 +485,41 @@ export class ControlHubInternal implements ControlHub { targetPosition_counts: number, targetTolerance_counts: number, ): Promise { - await this.sendCommand("setMotorTargetPosition", { - id: this.id, - motorChannel: motorChannel, - targetPositionCounts: targetPosition_counts, - targetToleranceCounts: targetTolerance_counts, - }); + return this.embedded.setMotorTargetPosition( + motorChannel, + targetPosition_counts, + targetTolerance_counts, + ); } async setMotorTargetVelocity( motorChannel: number, velocity_cps: number, ): Promise { - await this.sendCommand("setMotorTargetVelocity", { - id: this.id, - motorChannel: motorChannel, - velocityCps: velocity_cps, - }); + return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); } async setNewModuleAddress(newModuleAddress: number): Promise { - await this.sendCommand("setNewModuleAddress", { - id: this.id, - address: newModuleAddress, - }); + return this.embedded.setNewModuleAddress(newModuleAddress); } async setPhoneChargeControl(chargeEnable: boolean): Promise { - await this.sendCommand("setPhoneChargeControl", { - id: this.id, - enabled: chargeEnable, - }); + return this.embedded.setPhoneChargeControl(chargeEnable); } async setServoConfiguration( servoChannel: number, framePeriod: number, ): Promise { - await this.sendCommand("setServoConfiguration", { - id: this.id, - servoChannel: servoChannel, - framePeriod: framePeriod, - }); + return this.embedded.setServoConfiguration(servoChannel, framePeriod); } async setServoEnable(servoChannel: number, enable: boolean): Promise { - await this.sendCommand("setServoEnable", { - id: this.id, - servoChannel: servoChannel, - enabled: enable, - }); + return this.embedded.setServoEnable(servoChannel, enable); } async setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { - await this.sendCommand("setServoPulseWidth", { - id: this.id, - servoChannel: servoChannel, - pulseWidth: pulseWidth, - }); + return this.embedded.setServoPulseWidth(servoChannel, pulseWidth); } writeI2CMultipleBytes( @@ -702,7 +527,7 @@ export class ControlHubInternal implements ControlHub { slaveAddress: number, bytes: number[], ): Promise { - throw new Error("not implemented"); + return this.embedded.writeI2CMultipleBytes(i2cChannel, slaveAddress, bytes); } writeI2CReadMultipleBytes( @@ -711,7 +536,12 @@ export class ControlHubInternal implements ControlHub { numBytesToRead: number, startAddress: number, ): Promise { - throw new Error("not implemented"); + return this.embedded.writeI2CReadMultipleBytes( + i2cChannel, + slaveAddress, + numBytesToRead, + startAddress, + ); } writeI2CSingleByte( @@ -719,9 +549,41 @@ export class ControlHubInternal implements ControlHub { slaveAddress: number, byte: number, ): Promise { + return this.embedded.writeI2CSingleByte(i2cChannel, slaveAddress, byte); + } + + async addChild(hub: RevHub): Promise { throw new Error("not implemented"); } + async addChildByAddress(moduleAddress: number): Promise { + return this.addHubBySerialNumberAndAddress(this.serialNumber, moduleAddress); + } + + async addHubBySerialNumberAndAddress( + serialNumber: string, + moduleAddress: number, + ): Promise { + let id: any = this.openHub(serialNumber, moduleAddress, moduleAddress); + + let newHub = new ControlHubConnected( + true, + RevHubType.ExpansionHub, + this.sendCommand.bind(this), + serialNumber, + moduleAddress, + id, + ); + + this.usbChildren.push(newHub); + this.children.push(newHub); + + if (!newHub.isParentHub) { + throw new Error("A child hub with a serial number must also be a parent."); + } + return newHub; + } + async sendCommand(type: string, params: P, timeout: number = 1000): Promise { let key = this.keyGenerator++; let messagePayload = { @@ -734,7 +596,7 @@ export class ControlHubInternal implements ControlHub { payload: JSON.stringify(messagePayload), }; - this.webSocketConnection?.send(JSON.stringify(payload)); + this.webSocketConnection.send(JSON.stringify(payload)); let callbackPromise: Promise = new Promise((resolve, reject) => { this.currentActiveCommands.set(key, (response, error) => { @@ -752,6 +614,7 @@ export class ControlHubInternal implements ControlHub { let timer!: NodeJS.Timer; let timeoutPromise: Promise = new Promise((_, reject) => { timer = setTimeout(() => { + console.log(`Got timeout for ${type}`); reject(new TimeoutError()); }, timeout); }); @@ -761,16 +624,6 @@ export class ControlHubInternal implements ControlHub { }); } - async addChild(hub: RevHub): Promise { - throw new Error("not implemented"); - } - - async addChildByAddress(moduleAddress: number): Promise { - let id: any = await this.sendCommand("addChild", moduleAddress); - - return new ControlHubInternal("(embedded)", moduleAddress, id); - } - getAllDigitalInputs(): Promise { return Promise.resolve(0); } @@ -786,3 +639,37 @@ export class ControlHubInternal implements ControlHub { return Promise.resolve(undefined); } } + +export async function openUsbControlHubsAndChildren(): Promise { + let hubs = await openUsbControlHubs(); + let result: ControlHub[] = []; + + for (let hub of hubs) { + let controlHub = hub as ControlHubInternal; + let addresses: Record< + string, + { + serialNumber: string; + parentHubAddress: number; + childAddresses: number[]; + } + > = await controlHub.sendCommand("scanAndDiscover", {}, 20000); + + for (let serialNumber in addresses) { + if (serialNumber === "(embedded)") continue; + + let parentHubInfo = addresses[serialNumber]; + let parentHub = await controlHub.addHubBySerialNumberAndAddress( + serialNumber, + parentHubInfo.parentHubAddress, + ); + + for (let childAddress of parentHubInfo.childAddresses) { + await parentHub.addChildByAddress(childAddress); + } + } + result.push(controlHub); + } + + return result; +} diff --git a/packages/control-hub/src/internal/ControlHubConnected.ts b/packages/control-hub/src/internal/ControlHubConnected.ts new file mode 100644 index 00000000..457ab42f --- /dev/null +++ b/packages/control-hub/src/internal/ControlHubConnected.ts @@ -0,0 +1,641 @@ +import { + BulkInputData, + ClosedLoopControlAlgorithm, + DebugGroup, + DigitalChannelDirection, + ExpansionHub, + I2CReadStatus, + I2CSpeedCode, + I2CWriteStatus, + LedPattern, + ModuleInterface, + ModuleStatus, + ParentExpansionHub, + ParentRevHub, + PidCoefficients, + RevHub, + RevHubType, + Rgb, + VerbosityLevel, + Version, +} from "@rev-robotics/rev-hub-core"; + +export class ControlHubConnected implements ParentExpansionHub { + isParentHub: boolean; + type: RevHubType; + id: any; + serialNumber: string; + moduleAddress: number; + sendCommand: (name: string, params: P, timeout?: number) => Promise; + + isOpen: boolean = false; + + responseTimeoutMs = 1000; + + readonly children: RevHub[] = []; + + constructor( + isParent: boolean, + type: RevHubType, + sendCommand: (name: string, params: P, timeout?: number) => Promise, + serialNumber: string, + moduleAddress: number, + id: any, + ) { + this.isParentHub = isParent; + this.type = type; + this.id = id; + this.serialNumber = serialNumber; + this.moduleAddress = moduleAddress; + this.sendCommand = sendCommand; + } + + isParent(): this is ParentRevHub { + return this.isParentHub; + } + + close(): void {} + + async getAnalogInput(channel: number): Promise { + return await this.sendCommand("getAnalogInput", { + id: this.id, + channel: channel, + }); + } + + async get5VBusVoltage(): Promise { + return await this.sendCommand("get5VBusVoltage", { + id: this.id, + }); + } + + async getBatteryCurrent(): Promise { + return await this.sendCommand("getBatteryCurrent", { + id: this.id, + }); + } + + async getBatteryVoltage(): Promise { + return await this.sendCommand("getBatteryVoltage", { + id: this.id, + }); + } + + async getDigitalBusCurrent(): Promise { + return await this.sendCommand("getDigitalBusCurrent", { + id: this.id, + }); + } + + async getI2CCurrent(): Promise { + return await this.sendCommand("getI2CCurrent", { + id: this.id, + }); + } + + async getMotorCurrent(motorChannel: number): Promise { + return await this.sendCommand("getMotorCurrent", { + id: this.id, + }); + } + + async getServoCurrent(): Promise { + return await this.sendCommand("getMotorCurrent", { + id: this.id, + }); + } + + async getTemperature(): Promise { + return await this.sendCommand("getTemperature", { + id: this.id, + }); + } + + async getBulkInputData(): Promise { + return await this.sendCommand("getBulkInputData", { + id: this.id, + }); + } + + async getDigitalAllInputs(): Promise { + return await this.sendCommand("getAllDigitalInputs", { + id: this.id, + }); + } + + async getDigitalDirection(dioPin: number): Promise { + let isOutput = await this.sendCommand("getDigitalDirection", { + id: this.id, + channel: dioPin, + }); + + return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; + } + + async getDigitalSingleInput(dioPin: number): Promise { + return await this.sendCommand("getDigitalInput", { + id: this.id, + channel: dioPin, + }); + } + + async getFTDIResetControl(): Promise { + return await this.sendCommand("getFtdiResetControl", { + id: this.id, + }); + } + + async getI2CChannelConfiguration(i2cChannel: number): Promise { + let speedCode = await this.sendCommand("getI2CChannelConfiguration", { + id: this.id, + channel: i2cChannel, + }); + + return speedCode == 1 + ? I2CSpeedCode.SpeedCode400_Kbps + : I2CSpeedCode.SpeedCode100_Kbps; + } + + getI2CReadStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getI2CWriteStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + async getInterfacePacketID( + interfaceName: string, + functionNumber: number, + ): Promise { + return await this.sendCommand("getInterfacePacketId", { + id: this.id, + interfaceName: interfaceName, + functionNumber: functionNumber, + }); + } + + async getModuleLedColor(): Promise { + let result: { r: number; g: number; b: number } = await this.sendCommand( + "getLedColor", + { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + }, + ); + + return { + red: result.r, + green: result.g, + blue: result.b, + }; + } + + getModuleLedPattern(): Promise { + throw new Error("not implemented"); + } + + async getModuleStatus(clearStatusAfterResponse: boolean): Promise { + return await this.sendCommand("getModuleStatus", { + id: this.id, + }); + } + + async getMotorAtTarget(motorChannel: number): Promise { + return await this.sendCommand("getIsMotorAtTarget", { + id: this.id, + }); + } + + async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { + return await this.sendCommand("getMotorAlertLevel", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async getMotorChannelEnable(motorChannel: number): Promise { + return await this.sendCommand("getMotorChannelEnable", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async getMotorChannelMode( + motorChannel: number, + ): Promise<{ motorMode: number; floatAtZero: boolean }> { + return await this.sendCommand("getMotorMode", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async getMotorConstantPower(motorChannel: number): Promise { + return await this.sendCommand("getMotorConstantPower", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async getMotorEncoderPosition(motorChannel: number): Promise { + return await this.sendCommand("getMotorEncoderPosition", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async getMotorPIDCoefficients( + motorChannel: number, + motorMode: number, + ): Promise { + let result: { p: number; i: number; d: number } = await this.sendCommand( + "getMotorPidCoefficients", + { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }, + ); + + return { + p: result.p, + i: result.i, + d: result.d, + algorithm: ClosedLoopControlAlgorithm.Pid, + }; + } + + async getMotorTargetPosition( + motorChannel: number, + ): Promise<{ targetPosition: number; targetTolerance: number }> { + let result: { targetPositionCounts: number; targetToleranceCounts: number } = + await this.sendCommand("getMotorTargetPosition", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + motorChannel: motorChannel, + }); + + return { + targetPosition: result.targetPositionCounts, + targetTolerance: result.targetToleranceCounts, + }; + } + + async getMotorTargetVelocity(motorChannel: number): Promise { + return await this.sendCommand("getMotorTargetVelocity", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async getPhoneChargeControl(): Promise { + return await this.sendCommand("getPhoneChargeControl", { + id: this.id, + }); + } + + async getServoConfiguration(servoChannel: number): Promise { + return await this.sendCommand("getServoConfiguration", { + id: this.id, + servoChannel: servoChannel, + }); + } + + async getServoEnable(servoChannel: number): Promise { + return await this.sendCommand("getServoEnable", { + id: this.id, + servoChannel: servoChannel, + }); + } + + async getServoPulseWidth(servoChannel: number): Promise { + return await this.sendCommand("getServoPulseWidth", { + id: this.id, + servoChannel: servoChannel, + }); + } + + async injectDataLogHint(hintText: string): Promise { + await this.sendCommand("injectDebugLogHint", { + id: this.id, + hint: hintText, + }); + } + + isExpansionHub(): this is ExpansionHub { + return true; + } + + on(eventName: "error", listener: (error: Error) => void): RevHub { + throw new Error("not implemented"); + } + + async queryInterface(interfaceName: string): Promise { + let result: { name: string; firstPacketId: number; numberIds: number } = + await this.sendCommand("queryInterface", { + serialNumber: this.serialNumber, + moduleAddress: this.moduleAddress, + interfaceName: interfaceName, + }); + + return { + name: result.name, + firstPacketID: result.firstPacketId, + numberIDValues: result.numberIds, + }; + } + + readI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + ): Promise { + throw new Error("not implemented"); + } + + readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + throw new Error("not implemented"); + } + + async readVersion(): Promise { + let versionString = await this.readVersionString(); + //ToDo(landry) parse version string + throw new Error("not implemented"); + } + + async readVersionString(): Promise { + return await this.sendCommand("readVersionString", { + id: this.id, + }); + } + + async resetMotorEncoder(motorChannel: number): Promise { + await this.sendCommand("resetMotorEncoder", { + id: this.id, + motorChannel: motorChannel, + }); + } + + async sendFailSafe(): Promise { + await this.sendCommand("readVersionString", { + id: this.id, + }); + } + + async sendKeepAlive(): Promise {} + + async sendReadCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + sendWriteCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + async setDebugLogLevel( + debugGroup: DebugGroup, + verbosityLevel: VerbosityLevel, + ): Promise { + await this.sendCommand("readVersionString", { + id: this.id, + debugGroup: debugGroup, + verbosityLevel: verbosityLevel, + }); + } + + async setDigitalAllOutputs(bitPackedField: number): Promise { + await this.sendCommand("readVersionString", { + id: this.id, + bitField: bitPackedField, + }); + } + + async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { + await this.sendCommand("readVersionString", { + id: this.id, + pin: dioPin, + isOutput: direction == DigitalChannelDirection.Output, + }); + } + + async setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { + await this.sendCommand("readVersionString", { + id: this.id, + pin: dioPin, + value: value ?? false, + }); + } + + async setFTDIResetControl(ftdiResetControl: boolean): Promise { + await this.sendCommand("setFtdiResetControl", { + id: this.id, + }); + } + + async setI2CChannelConfiguration( + i2cChannel: number, + speedCode: I2CSpeedCode, + ): Promise { + await this.sendCommand("setI2CChannelConfiguration", { + id: this.id, + i2cChannel: i2cChannel, + speedCode: speedCode, + }); + } + + async setModuleLedColor(red: number, green: number, blue: number): Promise { + await this.sendCommand("setLedColor", { + id: this.id, + r: red, + g: green, + b: blue, + }); + } + + async setModuleLedPattern(ledPattern: LedPattern): Promise { + await this.sendCommand("setLedPattern", { + id: this.id, + rgbtPatternStep0: ledPattern.rgbtPatternStep0, + rgbtPatternStep1: ledPattern.rgbtPatternStep1, + rgbtPatternStep2: ledPattern.rgbtPatternStep2, + rgbtPatternStep3: ledPattern.rgbtPatternStep3, + rgbtPatternStep4: ledPattern.rgbtPatternStep4, + rgbtPatternStep5: ledPattern.rgbtPatternStep5, + rgbtPatternStep6: ledPattern.rgbtPatternStep6, + rgbtPatternStep7: ledPattern.rgbtPatternStep7, + rgbtPatternStep8: ledPattern.rgbtPatternStep8, + rgbtPatternStep9: ledPattern.rgbtPatternStep9, + rgbtPatternStep10: ledPattern.rgbtPatternStep10, + rgbtPatternStep11: ledPattern.rgbtPatternStep11, + rgbtPatternStep12: ledPattern.rgbtPatternStep12, + rgbtPatternStep13: ledPattern.rgbtPatternStep13, + rgbtPatternStep14: ledPattern.rgbtPatternStep14, + rgbtPatternStep15: ledPattern.rgbtPatternStep15, + }); + } + + async setMotorChannelCurrentAlertLevel( + motorChannel: number, + currentLimit_mA: number, + ): Promise { + await this.sendCommand("setMotorAlertLevel", { + id: this.id, + motorChannel: motorChannel, + currentLimit_mA: currentLimit_mA, + }); + } + + async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { + await this.sendCommand("setMotorEnabled", { + id: this.id, + motorChannel: motorChannel, + enable: enable, + }); + } + + async setMotorChannelMode( + motorChannel: number, + motorMode: number, + floatAtZero: boolean, + ): Promise { + await this.sendCommand("setMotorChannelMode", { + id: this.id, + motorChannel: motorChannel, + motorMode: motorMode, + floatAtZero: floatAtZero, + }); + } + + async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { + await this.sendCommand("setMotorConstantPower", { + id: this.id, + motorChannel: motorChannel, + motorPower: powerLevel, + }); + } + + async setMotorPIDCoefficients( + motorChannel: number, + motorMode: number, + pid: PidCoefficients, + ): Promise { + await this.sendCommand("setMotorPidCoefficients", { + id: this.id, + motorChannel: motorChannel, + motorMode: motorMode, + p: pid.p, + i: pid.i, + d: pid.d, + }); + } + + async setMotorTargetPosition( + motorChannel: number, + targetPosition_counts: number, + targetTolerance_counts: number, + ): Promise { + await this.sendCommand("setMotorTargetPosition", { + id: this.id, + motorChannel: motorChannel, + targetPositionCounts: targetPosition_counts, + targetToleranceCounts: targetTolerance_counts, + }); + } + + async setMotorTargetVelocity( + motorChannel: number, + velocity_cps: number, + ): Promise { + await this.sendCommand("setMotorTargetVelocity", { + id: this.id, + motorChannel: motorChannel, + velocityCps: velocity_cps, + }); + } + + async setNewModuleAddress(newModuleAddress: number): Promise { + await this.sendCommand("setNewModuleAddress", { + id: this.id, + address: newModuleAddress, + }); + } + + async setPhoneChargeControl(chargeEnable: boolean): Promise { + await this.sendCommand("setPhoneChargeControl", { + id: this.id, + enabled: chargeEnable, + }); + } + + async setServoConfiguration( + servoChannel: number, + framePeriod: number, + ): Promise { + await this.sendCommand("setServoConfiguration", { + id: this.id, + servoChannel: servoChannel, + framePeriod: framePeriod, + }); + } + + async setServoEnable(servoChannel: number, enable: boolean): Promise { + await this.sendCommand("setServoEnable", { + id: this.id, + servoChannel: servoChannel, + enabled: enable, + }); + } + + async setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { + await this.sendCommand("setServoPulseWidth", { + id: this.id, + servoChannel: servoChannel, + pulseWidth: pulseWidth, + }); + } + + writeI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + bytes: number[], + ): Promise { + throw new Error("not implemented"); + } + + writeI2CReadMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + startAddress: number, + ): Promise { + throw new Error("not implemented"); + } + + writeI2CSingleByte( + i2cChannel: number, + slaveAddress: number, + byte: number, + ): Promise { + throw new Error("not implemented"); + } + + async addChildByAddress(moduleAddress: number): Promise { + let id = await this.sendCommand("openHub", { + parentSerialNumber: this.serialNumber, + parentHubAddress: this.moduleAddress, + hubAddress: moduleAddress, + }); + let newHub = new ControlHubConnected( + false, + RevHubType.ExpansionHub, + this.sendCommand, + this.serialNumber, + moduleAddress, + id, + ); + + this.children.push(newHub); + + return newHub; + } +} diff --git a/packages/core/src/ControlHub.ts b/packages/core/src/ControlHub.ts index 01ce2a91..b59bfc0e 100644 --- a/packages/core/src/ControlHub.ts +++ b/packages/core/src/ControlHub.ts @@ -1,4 +1,9 @@ import { ExpansionHub } from "./ExpansionHub.js"; import { ParentRevHub } from "./RevHub.js"; -export interface ControlHub extends ExpansionHub, ParentRevHub {} +export interface ControlHub extends ExpansionHub, ParentRevHub { + addHubBySerialNumberAndAddress( + serialNumber: string, + moduleAddress: number, + ): Promise; +} diff --git a/packages/sample/src/HubStringify.ts b/packages/sample/src/HubStringify.ts index 95d63f84..7b25a516 100644 --- a/packages/sample/src/HubStringify.ts +++ b/packages/sample/src/HubStringify.ts @@ -1,16 +1,17 @@ -import { RevHub } from "@rev-robotics/rev-hub-core"; +import { ControlHub, RevHub } from "@rev-robotics/rev-hub-core"; -export function hubHierarchyToString(hub: RevHub): string { - let serialNumberText: string = ""; - if (hub.isParent()) { - serialNumberText = `(${hub.serialNumber})`; - } - let result = `RevHub ${serialNumberText}: ${hub.moduleAddress}\n`; +export function controlHubHierarchyToString(hub: ControlHub): string { + let result = ""; + result = `Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n`; + for (const child of hub.children) { + if (child.isParent()) { + result += `\tUSB Hub: ${child.serialNumber} ${child.moduleAddress}\n`; - if (hub.isParent()) { - result = `USB Expansion Hub: ${hub.serialNumber} ${hub.moduleAddress}\n`; - for (const child of hub.children) { - result += `\tUSB Expansion Hub: ${child.moduleAddress}\n`; + for (const grandchild of child.children) { + result += `\t\tRS-485 Hub: ${grandchild.moduleAddress}\n`; + } + } else { + result += `\tRS-485 Hub: ${child.moduleAddress}\n`; } } diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index e11583fd..04c678eb 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -15,7 +15,7 @@ export async function openUsbControlHubs(): Promise { let port = await configureHubTcp(deviceClient); let serialNumber = device.id; - let hub = await openControlHub("(embedded)", 173, port); + let hub = await openControlHub(serialNumber, 173, port); controlHubs.push(hub); } } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index f1869951..67f06858 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,13 +1,15 @@ -import { hubHierarchyToString } from "../HubStringify.js"; -import { openConnectedControlHub } from "@rev-robotics/control-hub"; +import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub"; +import { controlHubHierarchyToString } from "../HubStringify.js"; +import { + openConnectedControlHub, openUsbControlHubsAndChildren, +} from "@rev-robotics/control-hub"; import { ExpansionHub } from "@rev-robotics/rev-hub-core"; -import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub" -import { openUsbControlHubs } from "../adb-setup.js"; export async function list() { - let usbControlHubs = await openUsbControlHubs(); + let usbControlHubs = await openUsbControlHubsAndChildren(); for (const hub of usbControlHubs) { - console.log(`USB Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n\n`); + let hierarchy = controlHubHierarchyToString(hub); + console.log(hierarchy); hub.close(); } @@ -23,7 +25,7 @@ export async function list() { console.log(`Got error:`); console.log(e); }); - console.log(hubHierarchyToString(hub)); + //console.log(controlHubHierarchyToString(hub)); } hubs.forEach((hub) => { hub.close(); diff --git a/tsconfig.json b/tsconfig.json index 5698646d..0a85fede 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,7 @@ "strict": true, "lib": ["es2021"], "target": "es2021", + "sourceMap": true, "types": [ "node" ], From e0ef0e50cb4979be03c59558f4a24e3657394345 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 15 Jun 2023 15:56:19 -0500 Subject: [PATCH 35/81] connect to other expansion hubs --- packages/control-hub/src/internal/ControlHub.ts | 4 ++-- packages/control-hub/src/internal/ControlHubConnected.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 67729e3e..a4295a10 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -132,7 +132,7 @@ export class ControlHubInternal implements ControlHub { this.embedded = new ControlHubConnected( true, RevHubType.ControlHub, - this.sendCommand, + this.sendCommand.bind(this), "(embedded)", this.moduleAddress, this.id, @@ -564,7 +564,7 @@ export class ControlHubInternal implements ControlHub { serialNumber: string, moduleAddress: number, ): Promise { - let id: any = this.openHub(serialNumber, moduleAddress, moduleAddress); + let id = await this.openHub(serialNumber, moduleAddress, moduleAddress); let newHub = new ControlHubConnected( true, diff --git a/packages/control-hub/src/internal/ControlHubConnected.ts b/packages/control-hub/src/internal/ControlHubConnected.ts index 457ab42f..bb3666d8 100644 --- a/packages/control-hub/src/internal/ControlHubConnected.ts +++ b/packages/control-hub/src/internal/ControlHubConnected.ts @@ -23,7 +23,7 @@ import { export class ControlHubConnected implements ParentExpansionHub { isParentHub: boolean; type: RevHubType; - id: any; + id: Exclude>; serialNumber: string; moduleAddress: number; sendCommand: (name: string, params: P, timeout?: number) => Promise; @@ -628,7 +628,7 @@ export class ControlHubConnected implements ParentExpansionHub { let newHub = new ControlHubConnected( false, RevHubType.ExpansionHub, - this.sendCommand, + this.sendCommand.bind(this), this.serialNumber, moduleAddress, id, From 3dcae659676032f7b7cc898356ab5942f8a6b3fb Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 23 Jun 2023 10:23:29 -0500 Subject: [PATCH 36/81] Add check for if a RevHub is a Control Hub --- packages/control-hub/src/internal/ControlHub.ts | 8 ++++---- packages/control-hub/src/internal/ControlHubConnected.ts | 7 ++++++- packages/core/src/RevHub.ts | 2 ++ packages/expansion-hub/src/internal/ExpansionHub.ts | 6 +++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index a4295a10..f7e11154 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -172,10 +172,6 @@ export class ControlHubInternal implements ControlHub { } } - private isControlHub(path: string): boolean { - return path.includes("_box") && path.includes("msm8916_64"); - } - async subscribe(): Promise { let payload = { namespace: "system", @@ -356,6 +352,10 @@ export class ControlHubInternal implements ControlHub { return true; } + isControlHub(): this is ControlHub { + return true; + } + on(eventName: "error", listener: (error: Error) => void): RevHub { return this.embedded.on(eventName, listener); } diff --git a/packages/control-hub/src/internal/ControlHubConnected.ts b/packages/control-hub/src/internal/ControlHubConnected.ts index bb3666d8..f752c3a1 100644 --- a/packages/control-hub/src/internal/ControlHubConnected.ts +++ b/packages/control-hub/src/internal/ControlHubConnected.ts @@ -1,6 +1,6 @@ import { BulkInputData, - ClosedLoopControlAlgorithm, + ClosedLoopControlAlgorithm, ControlHub, DebugGroup, DigitalChannelDirection, ExpansionHub, @@ -326,6 +326,11 @@ export class ControlHubConnected implements ParentExpansionHub { return true; } + isControlHub(): this is ControlHub { + //this class represents the expansion hub board, so it is not a control hub. + return false; + } + on(eventName: "error", listener: (error: Error) => void): RevHub { throw new Error("not implemented"); } diff --git a/packages/core/src/RevHub.ts b/packages/core/src/RevHub.ts index 383bcced..1ba7e9bb 100644 --- a/packages/core/src/RevHub.ts +++ b/packages/core/src/RevHub.ts @@ -1,5 +1,6 @@ import { RevHubType } from "./RevHubType.js"; import { ExpansionHub } from "./ExpansionHub.js"; +import { ControlHub } from "./ControlHub.js"; export interface RevHub { readonly moduleAddress: number; @@ -7,6 +8,7 @@ export interface RevHub { isParent(): this is ParentRevHub; isExpansionHub(): this is ExpansionHub; + isControlHub(): this is ControlHub; /** * Listen for errors that do not happen as a result of a specific function call diff --git a/packages/expansion-hub/src/internal/ExpansionHub.ts b/packages/expansion-hub/src/internal/ExpansionHub.ts index 117eb73e..3dd276a8 100644 --- a/packages/expansion-hub/src/internal/ExpansionHub.ts +++ b/packages/expansion-hub/src/internal/ExpansionHub.ts @@ -1,7 +1,7 @@ import { BulkInputData, ClosedLoopControlAlgorithm, - CommandNotSupportedError, + CommandNotSupportedError, ControlHub, DebugGroup, DigitalChannelDirection, DigitalState, @@ -66,6 +66,10 @@ export class ExpansionHubInternal implements ExpansionHub { return true; } + isControlHub(): this is ControlHub { + return false; + } + close(): void { //Closing a parent closes the serial port and all children if (this.isParent()) { From 66ce41ad000e05aee37e69d9bb3e6b2398711f6d Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 23 Jun 2023 10:23:51 -0500 Subject: [PATCH 37/81] Clarify naming --- packages/control-hub/src/internal/ControlHub.ts | 8 ++++---- ...HubConnected.ts => ControlHubConnectedExpansionHub.ts} | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename packages/control-hub/src/internal/{ControlHubConnected.ts => ControlHubConnectedExpansionHub.ts} (99%) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index f7e11154..08a709d2 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -27,7 +27,7 @@ import { } from "@rev-robotics/rev-hub-core"; import { openUsbControlHubs } from "rev-hub-cli/dist/adb-setup.js"; import { clearTimeout } from "timers"; -import { ControlHubConnected } from "./ControlHubConnected.js"; +import { ControlHubConnectedExpansionHub } from "./ControlHubConnectedExpansionHub.js"; export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; @@ -61,7 +61,7 @@ export class ControlHubInternal implements ControlHub { * The board for this control hub. All Expansion Hub commands go through * this delegate. */ - private embedded!: ControlHubConnected; + private embedded!: ControlHubConnectedExpansionHub; private webSocketConnection!: WebSocket; private currentActiveCommands = new Map< @@ -129,7 +129,7 @@ export class ControlHubInternal implements ControlHub { this.id = await this.openHub("(embedded)", this.moduleAddress); - this.embedded = new ControlHubConnected( + this.embedded = new ControlHubConnectedExpansionHub( true, RevHubType.ControlHub, this.sendCommand.bind(this), @@ -566,7 +566,7 @@ export class ControlHubInternal implements ControlHub { ): Promise { let id = await this.openHub(serialNumber, moduleAddress, moduleAddress); - let newHub = new ControlHubConnected( + let newHub = new ControlHubConnectedExpansionHub( true, RevHubType.ExpansionHub, this.sendCommand.bind(this), diff --git a/packages/control-hub/src/internal/ControlHubConnected.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts similarity index 99% rename from packages/control-hub/src/internal/ControlHubConnected.ts rename to packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index f752c3a1..a935b3cc 100644 --- a/packages/control-hub/src/internal/ControlHubConnected.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -20,7 +20,7 @@ import { Version, } from "@rev-robotics/rev-hub-core"; -export class ControlHubConnected implements ParentExpansionHub { +export class ControlHubConnectedExpansionHub implements ParentExpansionHub { isParentHub: boolean; type: RevHubType; id: Exclude>; @@ -630,7 +630,7 @@ export class ControlHubConnected implements ParentExpansionHub { parentHubAddress: this.moduleAddress, hubAddress: moduleAddress, }); - let newHub = new ControlHubConnected( + let newHub = new ControlHubConnectedExpansionHub( false, RevHubType.ExpansionHub, this.sendCommand.bind(this), From b7495661d27023493fff744f86d40ebf29ca2eb4 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 28 Jun 2023 16:51:07 -0500 Subject: [PATCH 38/81] formatting in HubStringify and restore deleted method --- packages/sample/src/HubStringify.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/sample/src/HubStringify.ts b/packages/sample/src/HubStringify.ts index 7b25a516..e7938bab 100644 --- a/packages/sample/src/HubStringify.ts +++ b/packages/sample/src/HubStringify.ts @@ -1,8 +1,7 @@ import { ControlHub, RevHub } from "@rev-robotics/rev-hub-core"; export function controlHubHierarchyToString(hub: ControlHub): string { - let result = ""; - result = `Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n`; + let result = `Control Hub: ${hub.serialNumber} ${hub.moduleAddress}\n`; for (const child of hub.children) { if (child.isParent()) { result += `\tUSB Hub: ${child.serialNumber} ${child.moduleAddress}\n`; @@ -17,3 +16,19 @@ export function controlHubHierarchyToString(hub: ControlHub): string { return result; } + +export function hubHierarchyToString(hub: RevHub): string { + let serialNumberText: string = ""; + if (hub.isParent()) { + serialNumberText = `(${hub.serialNumber})`; + } + let result = `RevHub ${serialNumberText}: ${hub.moduleAddress}\n`; + + if (hub.isParent()) { + for (const child of hub.children) { + result += `\tRevHub: ${child.moduleAddress}\n`; + } + } + + return result; +} From 8950c5dcc24c1c174f0e49f572c43b8ad162193c Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 29 Jun 2023 09:03:38 -0500 Subject: [PATCH 39/81] Don't add embedded as a child of control hub --- packages/control-hub/src/internal/ControlHub.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 08a709d2..6649268c 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -138,8 +138,6 @@ export class ControlHubInternal implements ControlHub { this.id, ); - this.children.push(this.embedded); - if ( apiVersion.majorVersion !== this.supportedManualControlMajorVersion || apiVersion.minorVersion < this.supportedManualControlMinorVersion From 73eb189e9ecc38058d54df5b962746f660469bdd Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 29 Jun 2023 09:04:38 -0500 Subject: [PATCH 40/81] properly close control hub --- packages/control-hub/src/internal/ControlHub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 6649268c..1cab76e4 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -193,7 +193,7 @@ export class ControlHubInternal implements ControlHub { close() { this.embedded.close(); - this.webSocketConnection.close(); + this.sendCommand("stop", {}).then(() => this.webSocketConnection.close()); } async getAnalogInput(channel: number): Promise { From 4f3080feaf590d803688165766dbb868a99ae3cd Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 29 Jun 2023 09:23:44 -0500 Subject: [PATCH 41/81] fixes for adding children --- .../control-hub/src/internal/ControlHub.ts | 29 ++++++++++++++----- packages/core/src/ControlHub.ts | 2 +- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 1cab76e4..7dbe2d75 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -24,6 +24,7 @@ import { PidfCoefficients, VerbosityLevel, Version, + ParentExpansionHub, } from "@rev-robotics/rev-hub-core"; import { openUsbControlHubs } from "rev-hub-cli/dist/adb-setup.js"; import { clearTimeout } from "timers"; @@ -550,18 +551,30 @@ export class ControlHubInternal implements ControlHub { return this.embedded.writeI2CSingleByte(i2cChannel, slaveAddress, byte); } - async addChild(hub: RevHub): Promise { - throw new Error("not implemented"); - } - async addChildByAddress(moduleAddress: number): Promise { - return this.addHubBySerialNumberAndAddress(this.serialNumber, moduleAddress); + let id = await this.openHub("(embedded)", this.moduleAddress, moduleAddress); + + let newHub = new ControlHubConnectedExpansionHub( + false, + RevHubType.ExpansionHub, + this.sendCommand.bind(this), + "(embedded)", + moduleAddress, + id, + ); + + this.children.push(newHub); + + if (newHub.isParentHub) { + throw new Error("A child hub without a serial number must not be a parent."); + } + return newHub; } - async addHubBySerialNumberAndAddress( + async addUsbConnectedHub( serialNumber: string, moduleAddress: number, - ): Promise { + ): Promise { let id = await this.openHub(serialNumber, moduleAddress, moduleAddress); let newHub = new ControlHubConnectedExpansionHub( @@ -657,7 +670,7 @@ export async function openUsbControlHubsAndChildren(): Promise { if (serialNumber === "(embedded)") continue; let parentHubInfo = addresses[serialNumber]; - let parentHub = await controlHub.addHubBySerialNumberAndAddress( + let parentHub = await controlHub.addUsbConnectedHub( serialNumber, parentHubInfo.parentHubAddress, ); diff --git a/packages/core/src/ControlHub.ts b/packages/core/src/ControlHub.ts index b59bfc0e..7e835847 100644 --- a/packages/core/src/ControlHub.ts +++ b/packages/core/src/ControlHub.ts @@ -2,7 +2,7 @@ import { ExpansionHub } from "./ExpansionHub.js"; import { ParentRevHub } from "./RevHub.js"; export interface ControlHub extends ExpansionHub, ParentRevHub { - addHubBySerialNumberAndAddress( + addUsbConnectedHub( serialNumber: string, moduleAddress: number, ): Promise; From 89160864c168650ad383b367c60182318f98c185 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 29 Jun 2023 09:42:07 -0500 Subject: [PATCH 42/81] update commands to match latest spec --- .../control-hub/src/internal/ControlHub.ts | 6 +- .../ControlHubConnectedExpansionHub.ts | 297 ++++++++++-------- 2 files changed, 168 insertions(+), 135 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 7dbe2d75..cd4be920 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -245,10 +245,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getDigitalDirection(dioPin); } - async getDigitalSingleInput(dioPin: number): Promise { - return this.embedded.getDigitalSingleInput(dioPin); - } - async getFTDIResetControl(): Promise { return this.embedded.getFTDIResetControl(); } @@ -422,7 +418,7 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setDigitalDirection(dioPin, direction); } - async setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { + async setDigitalSingleOutput(dioPin: number, value: DigitalState): Promise { return this.embedded.setDigitalSingleOutput(dioPin, value); } diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index a935b3cc..60a79c81 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -2,7 +2,7 @@ import { BulkInputData, ClosedLoopControlAlgorithm, ControlHub, DebugGroup, - DigitalChannelDirection, + DigitalChannelDirection, DigitalState, ExpansionHub, I2CReadStatus, I2CSpeedCode, @@ -19,6 +19,7 @@ import { VerbosityLevel, Version, } from "@rev-robotics/rev-hub-core"; +import { EventEmitter } from "events"; export class ControlHubConnectedExpansionHub implements ParentExpansionHub { isParentHub: boolean; @@ -33,6 +34,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { responseTimeoutMs = 1000; readonly children: RevHub[] = []; + private emitter = new EventEmitter(); constructor( isParent: boolean, @@ -54,101 +56,126 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return this.isParentHub; } - close(): void {} + close(): void { + // noinspection JSIgnoredPromiseFromCall + this.sendCommand("closeHub", { + hId: this.id, + }); + } async getAnalogInput(channel: number): Promise { return await this.sendCommand("getAnalogInput", { - id: this.id, + hId: this.id, channel: channel, }); } async get5VBusVoltage(): Promise { return await this.sendCommand("get5VBusVoltage", { - id: this.id, + hId: this.id, }); } async getBatteryCurrent(): Promise { return await this.sendCommand("getBatteryCurrent", { - id: this.id, + hId: this.id, }); } async getBatteryVoltage(): Promise { return await this.sendCommand("getBatteryVoltage", { - id: this.id, + hId: this.id, }); } async getDigitalBusCurrent(): Promise { return await this.sendCommand("getDigitalBusCurrent", { - id: this.id, + hId: this.id, }); } async getI2CCurrent(): Promise { return await this.sendCommand("getI2CCurrent", { - id: this.id, + hId: this.id, }); } async getMotorCurrent(motorChannel: number): Promise { return await this.sendCommand("getMotorCurrent", { - id: this.id, + hId: this.id, + c: motorChannel, }); } async getServoCurrent(): Promise { return await this.sendCommand("getMotorCurrent", { - id: this.id, + hId: this.id, }); } async getTemperature(): Promise { return await this.sendCommand("getTemperature", { - id: this.id, + hId: this.id, }); } async getBulkInputData(): Promise { - return await this.sendCommand("getBulkInputData", { - id: this.id, + let rawData: any = await this.sendCommand("getBulkInputData", { + hId: this.id, }); + + return { + analog0_mV: rawData.a0, + analog1_mV: rawData.a1, + analog2_mV: rawData.a3, + analog3_mV: rawData.a4, + digitalInputs: rawData.diBf, + motor0position_enc: rawData.m0ep, + motor1position_enc: rawData.m1ep, + motor2position_enc: rawData.m2ep, + motor3position_enc: rawData.m3ep, + motor0velocity_cps: rawData.m0v, + motor1velocity_cps: rawData.m1v, + motor2velocity_cps: rawData.m2v, + motor3velocity_cps: rawData.m3v, + motorStatus: rawData.msBf, + }; } async getDigitalAllInputs(): Promise { return await this.sendCommand("getAllDigitalInputs", { - id: this.id, + hId: this.id, }); } async getDigitalDirection(dioPin: number): Promise { let isOutput = await this.sendCommand("getDigitalDirection", { - id: this.id, + hId: this.id, channel: dioPin, }); return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; } - async getDigitalSingleInput(dioPin: number): Promise { - return await this.sendCommand("getDigitalInput", { - id: this.id, - channel: dioPin, + async getDigitalInput(dioPin: number): Promise { + let state: boolean = await this.sendCommand("getDigitalInput", { + hId: this.id, + c: dioPin, }); + + return state ? DigitalState.HIGH: DigitalState.LOW; } async getFTDIResetControl(): Promise { return await this.sendCommand("getFtdiResetControl", { - id: this.id, + hId: this.id, }); } async getI2CChannelConfiguration(i2cChannel: number): Promise { let speedCode = await this.sendCommand("getI2CChannelConfiguration", { - id: this.id, - channel: i2cChannel, + hId: this.id, + c: i2cChannel, }); return speedCode == 1 @@ -169,7 +196,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { functionNumber: number, ): Promise { return await this.sendCommand("getInterfacePacketId", { - id: this.id, + hId: this.id, interfaceName: interfaceName, functionNumber: functionNumber, }); @@ -179,8 +206,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { let result: { r: number; g: number; b: number } = await this.sendCommand( "getLedColor", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + hId: this.id, }, ); @@ -195,29 +221,30 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { throw new Error("not implemented"); } - async getModuleStatus(clearStatusAfterResponse: boolean): Promise { + async getModuleStatus(_: boolean): Promise { return await this.sendCommand("getModuleStatus", { - id: this.id, + hId: this.id, }); } async getMotorAtTarget(motorChannel: number): Promise { return await this.sendCommand("getIsMotorAtTarget", { - id: this.id, + hId: this.id, + c: motorChannel, }); } async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { return await this.sendCommand("getMotorAlertLevel", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } async getMotorChannelEnable(motorChannel: number): Promise { return await this.sendCommand("getMotorChannelEnable", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } @@ -225,22 +252,22 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { motorChannel: number, ): Promise<{ motorMode: number; floatAtZero: boolean }> { return await this.sendCommand("getMotorMode", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } async getMotorConstantPower(motorChannel: number): Promise { return await this.sendCommand("getMotorConstantPower", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } async getMotorEncoderPosition(motorChannel: number): Promise { return await this.sendCommand("getMotorEncoderPosition", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } @@ -251,9 +278,9 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { let result: { p: number; i: number; d: number } = await this.sendCommand( "getMotorPidCoefficients", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, + m: motorMode, }, ); @@ -268,56 +295,57 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { - let result: { targetPositionCounts: number; targetToleranceCounts: number } = - await this.sendCommand("getMotorTargetPosition", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, - motorChannel: motorChannel, - }); + let result: { tpc: number; ttc: number } = await this.sendCommand( + "getMotorTargetPosition", + { + hId: this.id, + c: motorChannel, + }, + ); return { - targetPosition: result.targetPositionCounts, - targetTolerance: result.targetToleranceCounts, + targetPosition: result.tpc, + targetTolerance: result.ttc, }; } async getMotorTargetVelocity(motorChannel: number): Promise { return await this.sendCommand("getMotorTargetVelocity", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } async getPhoneChargeControl(): Promise { return await this.sendCommand("getPhoneChargeControl", { - id: this.id, + hId: this.id, }); } async getServoConfiguration(servoChannel: number): Promise { return await this.sendCommand("getServoConfiguration", { - id: this.id, - servoChannel: servoChannel, + hId: this.id, + c: servoChannel, }); } async getServoEnable(servoChannel: number): Promise { return await this.sendCommand("getServoEnable", { - id: this.id, - servoChannel: servoChannel, + hId: this.id, + c: servoChannel, }); } async getServoPulseWidth(servoChannel: number): Promise { return await this.sendCommand("getServoPulseWidth", { - id: this.id, - servoChannel: servoChannel, + hId: this.id, + c: servoChannel, }); } async injectDataLogHint(hintText: string): Promise { await this.sendCommand("injectDebugLogHint", { - id: this.id, + hId: this.id, hint: hintText, }); } @@ -331,15 +359,18 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return false; } - on(eventName: "error", listener: (error: Error) => void): RevHub { - throw new Error("not implemented"); + on( + eventName: "error" | "statusChanged" | "addressChanged" | "sessionEnded", + listener: (...param: any) => void, + ): this { + this.emitter.on(eventName, listener); + return this; } async queryInterface(interfaceName: string): Promise { let result: { name: string; firstPacketId: number; numberIds: number } = await this.sendCommand("queryInterface", { - serialNumber: this.serialNumber, - moduleAddress: this.moduleAddress, + hId: this.id, interfaceName: interfaceName, }); @@ -364,26 +395,36 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { async readVersion(): Promise { let versionString = await this.readVersionString(); - //ToDo(landry) parse version string - throw new Error("not implemented"); + let parts = versionString.split("."); + if (parts.length != 3) { + throw new Error(`Version ${versionString} does not have 3 parts`); + } + return { + majorVersion: Number(parts[0]), + minorVersion: Number(parts[1]), + engineeringRevision: Number(parts[2]), + minorHwRevision: 0, //hardcoded in RHSPlib_device_control.c + majorHwRevision: 2, //hardcoded in RHSPlib_device_control.c + hwType: 0x311153, //hardcoded in RHSPlib_device_control.c + }; } async readVersionString(): Promise { return await this.sendCommand("readVersionString", { - id: this.id, + hId: this.id, }); } async resetMotorEncoder(motorChannel: number): Promise { await this.sendCommand("resetMotorEncoder", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, }); } async sendFailSafe(): Promise { await this.sendCommand("readVersionString", { - id: this.id, + hId: this.id, }); } @@ -402,7 +443,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { verbosityLevel: VerbosityLevel, ): Promise { await this.sendCommand("readVersionString", { - id: this.id, + hId: this.id, debugGroup: debugGroup, verbosityLevel: verbosityLevel, }); @@ -410,47 +451,43 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { async setDigitalAllOutputs(bitPackedField: number): Promise { await this.sendCommand("readVersionString", { - id: this.id, - bitField: bitPackedField, + hId: this.id, + bf: bitPackedField, }); } async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { await this.sendCommand("readVersionString", { - id: this.id, - pin: dioPin, - isOutput: direction == DigitalChannelDirection.Output, + hId: this.id, + c: dioPin, + o: direction == DigitalChannelDirection.Output, }); } - async setDigitalSingleOutput(dioPin: number, value?: boolean): Promise { + async setDigitalSingleOutput(dioPin: number, value: DigitalState): Promise { await this.sendCommand("readVersionString", { - id: this.id, - pin: dioPin, - value: value ?? false, + hId: this.id, + c: dioPin, + v: value.isHigh(), }); } - async setFTDIResetControl(ftdiResetControl: boolean): Promise { - await this.sendCommand("setFtdiResetControl", { - id: this.id, - }); - } + async setFTDIResetControl(_: boolean): Promise {} async setI2CChannelConfiguration( i2cChannel: number, speedCode: I2CSpeedCode, ): Promise { await this.sendCommand("setI2CChannelConfiguration", { - id: this.id, - i2cChannel: i2cChannel, - speedCode: speedCode, + hId: this.id, + c: i2cChannel, + sc: speedCode, }); } async setModuleLedColor(red: number, green: number, blue: number): Promise { await this.sendCommand("setLedColor", { - id: this.id, + hId: this.id, r: red, g: green, b: blue, @@ -459,23 +496,23 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { async setModuleLedPattern(ledPattern: LedPattern): Promise { await this.sendCommand("setLedPattern", { - id: this.id, - rgbtPatternStep0: ledPattern.rgbtPatternStep0, - rgbtPatternStep1: ledPattern.rgbtPatternStep1, - rgbtPatternStep2: ledPattern.rgbtPatternStep2, - rgbtPatternStep3: ledPattern.rgbtPatternStep3, - rgbtPatternStep4: ledPattern.rgbtPatternStep4, - rgbtPatternStep5: ledPattern.rgbtPatternStep5, - rgbtPatternStep6: ledPattern.rgbtPatternStep6, - rgbtPatternStep7: ledPattern.rgbtPatternStep7, - rgbtPatternStep8: ledPattern.rgbtPatternStep8, - rgbtPatternStep9: ledPattern.rgbtPatternStep9, - rgbtPatternStep10: ledPattern.rgbtPatternStep10, - rgbtPatternStep11: ledPattern.rgbtPatternStep11, - rgbtPatternStep12: ledPattern.rgbtPatternStep12, - rgbtPatternStep13: ledPattern.rgbtPatternStep13, - rgbtPatternStep14: ledPattern.rgbtPatternStep14, - rgbtPatternStep15: ledPattern.rgbtPatternStep15, + hId: this.id, + s0: ledPattern.rgbtPatternStep0, + s1: ledPattern.rgbtPatternStep1, + s2: ledPattern.rgbtPatternStep2, + s3: ledPattern.rgbtPatternStep3, + s4: ledPattern.rgbtPatternStep4, + s5: ledPattern.rgbtPatternStep5, + s6: ledPattern.rgbtPatternStep6, + s7: ledPattern.rgbtPatternStep7, + s8: ledPattern.rgbtPatternStep8, + s9: ledPattern.rgbtPatternStep9, + s10: ledPattern.rgbtPatternStep10, + s11: ledPattern.rgbtPatternStep11, + s12: ledPattern.rgbtPatternStep12, + s13: ledPattern.rgbtPatternStep13, + s14: ledPattern.rgbtPatternStep14, + s15: ledPattern.rgbtPatternStep15, }); } @@ -484,16 +521,16 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { currentLimit_mA: number, ): Promise { await this.sendCommand("setMotorAlertLevel", { - id: this.id, - motorChannel: motorChannel, - currentLimit_mA: currentLimit_mA, + hId: this.id, + c: motorChannel, + cl: currentLimit_mA, }); } async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { await this.sendCommand("setMotorEnabled", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, enable: enable, }); } @@ -504,17 +541,17 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { floatAtZero: boolean, ): Promise { await this.sendCommand("setMotorChannelMode", { - id: this.id, - motorChannel: motorChannel, - motorMode: motorMode, - floatAtZero: floatAtZero, + hId: this.id, + c: motorChannel, + m: motorMode, + faz: floatAtZero, }); } async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { await this.sendCommand("setMotorConstantPower", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, motorPower: powerLevel, }); } @@ -525,8 +562,8 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { pid: PidCoefficients, ): Promise { await this.sendCommand("setMotorPidCoefficients", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, motorMode: motorMode, p: pid.p, i: pid.i, @@ -540,8 +577,8 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { targetTolerance_counts: number, ): Promise { await this.sendCommand("setMotorTargetPosition", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, targetPositionCounts: targetPosition_counts, targetToleranceCounts: targetTolerance_counts, }); @@ -552,22 +589,22 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { velocity_cps: number, ): Promise { await this.sendCommand("setMotorTargetVelocity", { - id: this.id, - motorChannel: motorChannel, + hId: this.id, + c: motorChannel, velocityCps: velocity_cps, }); } async setNewModuleAddress(newModuleAddress: number): Promise { await this.sendCommand("setNewModuleAddress", { - id: this.id, + hId: this.id, address: newModuleAddress, }); } async setPhoneChargeControl(chargeEnable: boolean): Promise { await this.sendCommand("setPhoneChargeControl", { - id: this.id, + hId: this.id, enabled: chargeEnable, }); } @@ -577,24 +614,24 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { framePeriod: number, ): Promise { await this.sendCommand("setServoConfiguration", { - id: this.id, - servoChannel: servoChannel, + hId: this.id, + c: servoChannel, framePeriod: framePeriod, }); } async setServoEnable(servoChannel: number, enable: boolean): Promise { await this.sendCommand("setServoEnable", { - id: this.id, - servoChannel: servoChannel, + hId: this.id, + c: servoChannel, enabled: enable, }); } async setServoPulseWidth(servoChannel: number, pulseWidth: number): Promise { await this.sendCommand("setServoPulseWidth", { - id: this.id, - servoChannel: servoChannel, + hId: this.id, + c: servoChannel, pulseWidth: pulseWidth, }); } From 8b696cb7511688c12bc74e79f5571b3f093c32c2 Mon Sep 17 00:00:00 2001 From: NoahAndrews Date: Tue, 25 Jul 2023 13:11:47 -0500 Subject: [PATCH 43/81] Rename getExpansionHubOrThrow() to getRevHubOrThrow() --- packages/sample/src/main.ts | 64 ++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index 543ffe37..4273e722 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -96,7 +96,7 @@ program "green, 0.5FF0000 for half-second red.", ) .action(async (steps) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -110,7 +110,7 @@ program .command("get-pattern") .description("Get LED Pattern steps") .action(async () => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); }); @@ -123,7 +123,7 @@ program .command("led ") .description("Set LED color") .action(async (r, g, b) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); }); @@ -138,7 +138,7 @@ program .command("get-led") .description("Get LED color. Values are [0,255]") .action(async () => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -165,7 +165,7 @@ program .option("--continuous", "run continuously") .action(async (options) => { let isContinuous = options.continuous !== undefined; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -181,7 +181,7 @@ program "Start servo 0 for 2 seconds, then send failsafe. Wait 2 more seconds to close. The servo should stop after 2 seconds.", ) .action(async () => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -194,7 +194,7 @@ program .command("version") .description("Get firmware version") .action(async () => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); await firmwareVersion(hub); close(); @@ -217,7 +217,7 @@ digitalCommand } let digitalState = stateBoolean ? DigitalState.HIGH : DigitalState.LOW; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -235,7 +235,7 @@ digitalCommand let isContinuous = options.continuous !== undefined; let channelNumber = Number(channel); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -252,7 +252,7 @@ digitalCommand .action(async (options) => { let isContinuous = options.continuous !== undefined; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -272,7 +272,7 @@ digitalCommand let bitfieldValue = parseInt(bitfield, 2); let bitmaskValue = parseInt(bitmask, 2); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -293,7 +293,7 @@ motorCommand .action(async (channel, options) => { let isContinuous = options.continuous !== undefined; let channelNumber = Number(channel); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -310,7 +310,7 @@ motorCommand .description("Get the current encoder position of a motor") .action(async (channel, options) => { let channelNumber = Number(channel); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -335,7 +335,7 @@ pidCommand let pValue = Number(p); let iValue = Number(i); let dValue = Number(d); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -350,7 +350,7 @@ pidCommand .description("Get PID coefficients for regulated velocity mode for a motor") .action(async (channel) => { let channelNumber = Number(channel); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -416,7 +416,7 @@ alertCommand .description("Get motor alert current (mA)") .action(async (channel) => { let channelNumber = Number(channel); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -434,7 +434,7 @@ alertCommand .action(async (channel, current) => { let channelNumber = Number(channel); let currentValue = Number(current); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -452,7 +452,7 @@ motorCommand .action(async (channel, power) => { let channelNumber = Number(channel); let powerNumber = Number(power); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { hub.setMotorChannelEnable(channelNumber, false); @@ -468,7 +468,7 @@ motorCommand .action(async (channel, speed) => { let channelNumber = Number(channel); let speedNumber = Number(speed); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { hub.setMotorChannelEnable(channelNumber, false); @@ -486,7 +486,7 @@ motorCommand let positionNumber = Number(position); let toleranceNumber = Number(tolerance); let velocityNumber = Number(velocity); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { hub.setMotorChannelEnable(channelNumber, false); @@ -512,7 +512,7 @@ program .action(async (port, options) => { let isContinuous = options.continuous !== undefined; let portNumber = Number(port); - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -530,7 +530,7 @@ program "Specify --continuous to run continuously", ) .action(async (options) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); let isContinuous = options.continuous !== undefined; runOnSigint(() => { @@ -548,7 +548,7 @@ program ) .action(async (options) => { let isContinuous = options.continuous !== undefined; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); }); @@ -569,7 +569,7 @@ batteryCommand ) .action(async (options) => { let isContinuous = options.continuous !== undefined; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -585,7 +585,7 @@ batteryCommand .description("Read the battery current. Specify --continuous to run continuously") .action(async (options) => { let isContinuous = options.continuous !== undefined; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -603,7 +603,7 @@ program ) .action(async (options) => { let isContinuous = options.continuous !== undefined; - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -618,7 +618,7 @@ program .option("--continuous", "Run continuously") .description("Read the digital bus current. Specify --continuous to run continuously") .action(async (options) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); let isContinuous = options.continuous !== undefined; runOnSigint(() => { @@ -636,7 +636,7 @@ program "Read the total current through all servos. Specify --continuous to run continuously", ) .action(async (options) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); let isContinuous = options.continuous !== undefined; runOnSigint(() => { @@ -651,7 +651,7 @@ program .command("log ") .description("Inject a log hint") .action(async (text) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -669,7 +669,7 @@ program "DigitalIO, I2C, Motor0, Motor1, Motor2, or Motor3. Valid values for level are [0,3]", ) .action(async (group, level) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { close(); @@ -684,7 +684,7 @@ program .command("servo [frameWidth]") .description("Run a servo with pulse width and optional frame width") .action(async (channel, pulseWidth, frameWidth) => { - let [hub, close] = await getExpansionHubOrThrow(); + let [hub, close] = await getRevHubOrThrow(); let channelValue = Number(channel); let pulseWidthValue = Number(pulseWidth); let frameWidthValue = frameWidth ? Number(frameWidth) : 4000; @@ -703,7 +703,7 @@ program.parse(process.argv); * This method also returns a close method. Other hubs may need to be opened, so * prefer calling the returned close method over closing the hub directly. */ -async function getExpansionHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void]> { +async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void]> { let options = program.opts(); let serialNumber = options.serial; // options.child and options.parent are strings, so a specified address of "0" will be treated as truthy, and will not be ignored. From 7a9e27837b433e622feaf6c9fcf074e62f813aac Mon Sep 17 00:00:00 2001 From: NoahAndrews Date: Tue, 25 Jul 2023 13:31:08 -0500 Subject: [PATCH 44/81] Remove log message --- packages/control-hub/src/internal/ControlHub.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index cd4be920..5dcc6ac1 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -90,7 +90,6 @@ export class ControlHubInternal implements ControlHub { async open(ip: string = "192.168.43.1", port: string = "8081"): Promise { this.webSocketConnection = new WebSocket(`ws://${ip}:${port}`); - console.log(`Opening on port ${port}`); this.webSocketConnection.on("message", (data) => { let rawMessage = JSON.parse(data.toString()); From fcddd5af1c674523529aae23e7fc22a4dd190e71 Mon Sep 17 00:00:00 2001 From: NoahAndrews Date: Tue, 25 Jul 2023 13:50:29 -0500 Subject: [PATCH 45/81] Delete Control Hub discovery.ts file This library is not responsible for discovering Control Hubs. --- packages/control-hub/src/discovery.ts | 22 ---------------------- packages/control-hub/src/index.ts | 1 - 2 files changed, 23 deletions(-) delete mode 100644 packages/control-hub/src/discovery.ts diff --git a/packages/control-hub/src/discovery.ts b/packages/control-hub/src/discovery.ts deleted file mode 100644 index bb85d757..00000000 --- a/packages/control-hub/src/discovery.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ControlHubInternal } from "./internal/ControlHub.js"; -import { ControlHub } from "@rev-robotics/rev-hub-core"; - -export async function openConnectedControlHub(): Promise { - try { - return await createWiFiControlHub(); - } catch (e: any) { - return undefined; - } -} - -async function createWiFiControlHub(): Promise { - let hub = new ControlHubInternal("Placeholder"); - - if (!(await hub.isWiFiConnected())) { - throw new Error("Hub is not connected via WiFi"); - } - - await hub.open(); - - return hub; -} diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index 3ac46878..ed84121d 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,7 +1,6 @@ import { ControlHubInternal } from "./internal/ControlHub.js"; import { ControlHub } from "@rev-robotics/rev-hub-core"; -export { openConnectedControlHub } from "./discovery.js"; export { openUsbControlHubsAndChildren } from "./internal/ControlHub.js"; export async function openControlHub( From 314f3c97c6b576072ba6d4f3a1fdc27559c64914 Mon Sep 17 00:00:00 2001 From: NoahAndrews Date: Tue, 25 Jul 2023 13:52:21 -0500 Subject: [PATCH 46/81] Remove default values of private open() method, pass port as a number --- packages/control-hub/src/index.ts | 2 +- packages/control-hub/src/internal/ControlHub.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index ed84121d..04674178 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -9,6 +9,6 @@ export async function openControlHub( port: number, ): Promise { let hub = new ControlHubInternal(serialNumber); - await hub.open("127.0.0.1", (port + 1).toString()); + await hub.open("127.0.0.1", port + 1); return hub; } diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 5dcc6ac1..b9758b7e 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -88,7 +88,7 @@ export class ControlHubInternal implements ControlHub { return true; } - async open(ip: string = "192.168.43.1", port: string = "8081"): Promise { + async open(ip: string, port: number): Promise { this.webSocketConnection = new WebSocket(`ws://${ip}:${port}`); this.webSocketConnection.on("message", (data) => { From 3284f683999a678c038b983273b71e563e97c880 Mon Sep 17 00:00:00 2001 From: NoahAndrews Date: Tue, 25 Jul 2023 15:31:54 -0500 Subject: [PATCH 47/81] Add @types/ws dependency to Control Hub package --- package-lock.json | 2 ++ packages/control-hub/package.json | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 94400d63..69e68b15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7790,6 +7790,7 @@ "devDependencies": { "@types/node": "^16.18.18", "@types/semver": "^7.5.0", + "@types/ws": "^8.5.4", "typescript": "^5.0.2" }, "peerDependencies": { @@ -9153,6 +9154,7 @@ "@rev-robotics/rev-hub-core": "*", "@types/node": "^16.18.18", "@types/semver": "^7.5.0", + "@types/ws": "^8.5.4", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", "semver": "^7.5.1", diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 08750822..44953ff6 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -16,9 +16,10 @@ "devDependencies": { "@types/node": "^16.18.18", "@types/semver": "^7.5.0", + "@types/ws": "^8.5.4", "typescript": "^5.0.2" }, "scripts": { "build": "tsc" } -} \ No newline at end of file +} From 0f2451c4ecebfe87d3cad9105530740dca269eed Mon Sep 17 00:00:00 2001 From: Landry Date: Thu, 3 Aug 2023 11:17:58 -0500 Subject: [PATCH 48/81] fix some circular dependencies --- packages/control-hub/src/index.ts | 2 -- .../control-hub/src/internal/ControlHub.ts | 35 ------------------- 2 files changed, 37 deletions(-) diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index 04674178..c9dbf3fb 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,8 +1,6 @@ import { ControlHubInternal } from "./internal/ControlHub.js"; import { ControlHub } from "@rev-robotics/rev-hub-core"; -export { openUsbControlHubsAndChildren } from "./internal/ControlHub.js"; - export async function openControlHub( serialNumber: string, moduleAddress: number, diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index b9758b7e..a494b6e6 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -26,7 +26,6 @@ import { Version, ParentExpansionHub, } from "@rev-robotics/rev-hub-core"; -import { openUsbControlHubs } from "rev-hub-cli/dist/adb-setup.js"; import { clearTimeout } from "timers"; import { ControlHubConnectedExpansionHub } from "./ControlHubConnectedExpansionHub.js"; @@ -645,37 +644,3 @@ export class ControlHubInternal implements ControlHub { return Promise.resolve(undefined); } } - -export async function openUsbControlHubsAndChildren(): Promise { - let hubs = await openUsbControlHubs(); - let result: ControlHub[] = []; - - for (let hub of hubs) { - let controlHub = hub as ControlHubInternal; - let addresses: Record< - string, - { - serialNumber: string; - parentHubAddress: number; - childAddresses: number[]; - } - > = await controlHub.sendCommand("scanAndDiscover", {}, 20000); - - for (let serialNumber in addresses) { - if (serialNumber === "(embedded)") continue; - - let parentHubInfo = addresses[serialNumber]; - let parentHub = await controlHub.addUsbConnectedHub( - serialNumber, - parentHubInfo.parentHubAddress, - ); - - for (let childAddress of parentHubInfo.childAddresses) { - await parentHub.addChildByAddress(childAddress); - } - } - result.push(controlHub); - } - - return result; -} From 6176c3b43f4ec21c01cfc5d6e38c9eedd32e6edb Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 14:19:15 -0500 Subject: [PATCH 49/81] fix method names and remove call to removed method --- .../control-hub/src/internal/ControlHub.ts | 6 ++--- .../ControlHubConnectedExpansionHub.ts | 25 +++++++++++++++---- packages/sample/src/command/list.ts | 14 +++-------- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index a494b6e6..91b005f2 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -236,7 +236,7 @@ export class ControlHubInternal implements ControlHub { } async getDigitalAllInputs(): Promise { - return this.embedded.getDigitalAllInputs(); + return this.embedded.getAllDigitalInputs(); } async getDigitalDirection(dioPin: number): Promise { @@ -409,7 +409,7 @@ export class ControlHubInternal implements ControlHub { } async setDigitalAllOutputs(bitPackedField: number): Promise { - return this.embedded.setDigitalAllOutputs(bitPackedField); + return this.embedded.setAllDigitalOutputs(bitPackedField); } async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { @@ -417,7 +417,7 @@ export class ControlHubInternal implements ControlHub { } async setDigitalSingleOutput(dioPin: number, value: DigitalState): Promise { - return this.embedded.setDigitalSingleOutput(dioPin, value); + return this.embedded.setDigitalOutput(dioPin, value); } async setFTDIResetControl(ftdiResetControl: boolean): Promise { diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 60a79c81..3a980264 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -9,10 +9,10 @@ import { I2CWriteStatus, LedPattern, ModuleInterface, - ModuleStatus, + ModuleStatus, MotorMode, ParentExpansionHub, ParentRevHub, - PidCoefficients, + PidCoefficients, PidfCoefficients, RevHub, RevHubType, Rgb, @@ -142,7 +142,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } - async getDigitalAllInputs(): Promise { + async getAllDigitalInputs(): Promise { return await this.sendCommand("getAllDigitalInputs", { hId: this.id, }); @@ -449,7 +449,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setDigitalAllOutputs(bitPackedField: number): Promise { + async setAllDigitalOutputs(bitPackedField: number): Promise { await this.sendCommand("readVersionString", { hId: this.id, bf: bitPackedField, @@ -464,7 +464,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setDigitalSingleOutput(dioPin: number, value: DigitalState): Promise { + async setDigitalOutput(dioPin: number, value: DigitalState): Promise { await this.sendCommand("readVersionString", { hId: this.id, c: dioPin, @@ -680,4 +680,19 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return newHub; } + + getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { + return this.getMotorPIDCoefficients(motorChannel, motorMode); + } + + + async setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm, + pid: PidCoefficients | PidfCoefficients, + ): Promise { + //Todo(landry): handle pidf + await this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + } } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 67f06858..70c14dd3 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,24 +1,16 @@ import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub"; import { controlHubHierarchyToString } from "../HubStringify.js"; -import { - openConnectedControlHub, openUsbControlHubsAndChildren, -} from "@rev-robotics/control-hub"; -import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import {ControlHub, ExpansionHub} from "@rev-robotics/rev-hub-core"; +import {openUsbControlHubs} from "../adb-setup.js"; export async function list() { - let usbControlHubs = await openUsbControlHubsAndChildren(); + let usbControlHubs = await openUsbControlHubs(); for (const hub of usbControlHubs) { let hierarchy = controlHubHierarchyToString(hub); console.log(hierarchy); hub.close(); } - const controlHub = await openConnectedControlHub(); - if (controlHub) { - console.log(`WiFi Control Hub: ${controlHub.moduleAddress}\n\n`); - controlHub.close(); - } - const hubs: ExpansionHub[] = await openConnectedExpansionHubs(); for (const hub of hubs) { hub.on("error", (e: any) => { From a72d6fcbb0b7abba20e9b39e1d2a1bcdbd19b31f Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 14:58:56 -0500 Subject: [PATCH 50/81] Add control flag --- packages/sample/src/main.ts | 69 +++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index 4273e722..b9e51ab4 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -44,6 +44,7 @@ import { } from "./command/digital.js"; import { sendFailSafe } from "./command/failsafe.js"; import { queryInterface } from "./command/query.js"; +import {openUsbControlHubs} from "./adb-setup.js"; function runOnSigint(block: () => void) { process.on("SIGINT", () => { @@ -68,6 +69,9 @@ program .option( "-c --child
", "communicate with the specified child Expansion Hub instead of its parent; requires parent address to be specified when the parent is an Expansion Hub", + ).option( + "--control", + "Specify that this hub is a control hub" ); program @@ -699,7 +703,7 @@ program program.parse(process.argv); /** - * Returns the expansion hub referred to by the options provided to the program. + * Returns the rev hub referred to by the options provided to the program. * This method also returns a close method. Other hubs may need to be opened, so * prefer calling the returned close method over closing the hub directly. */ @@ -709,6 +713,7 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void // options.child and options.parent are strings, so a specified address of "0" will be treated as truthy, and will not be ignored. let childAddress = options.child ? Number(options.child) : undefined; let parentAddress = options.parent ? Number(options.parent) : undefined; + let isControlHub = options.control ?? false; if (childAddress !== undefined && (childAddress < 1 || childAddress > 255)) { throw new Error(`${childAddress} is not a valid child address`); } else if ( @@ -728,31 +733,51 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void "parent address must be specified if serial number is specified.", ); } - return openExpansionHubWithSerialNumber( - serialNumber, - parentAddress, - childAddress, - ); + if(isControlHub) { + let hubs = await openUsbControlHubs(); + return [hubs[0], () => { hubs.forEach((hub) => hub.close()) }]; + } else { + return openExpansionHubWithSerialNumber( + serialNumber, + parentAddress, + childAddress, + ); + } } else if (parentAddress !== undefined) { - return openExpansionHubWithAddress(parentAddress, childAddress); - } - - let connectedHubs: ParentExpansionHub[] = await openConnectedExpansionHubs(); - if (connectedHubs.length == 0) { - throw new Error("No hubs are connected"); - } - if (connectedHubs.length > 1) { - throw new Error("Multiple hubs connected. You must specify a serialNumber."); + if(isControlHub) { + let hubs = await openUsbControlHubs(); + return [hubs[0], () => { hubs.forEach((hub) => hub.close()) }]; + } else { + return openExpansionHubWithAddress(parentAddress, childAddress); + } } - // Open the only Hub that is connected - - let closeHubs = () => { - for (let hub of connectedHubs) { - hub.close(); + if(isControlHub) { + let hubs = await openUsbControlHubs(); + if (hubs.length == 0) { + throw new Error("No hubs are connected"); + } + if (hubs.length > 1) { + throw new Error("Multiple hubs connected. You must specify a serialNumber."); + } + return [hubs[0], () => { hubs.forEach((hub) => hub.close()) }]; + } else { + let connectedHubs: ParentExpansionHub[] = await openConnectedExpansionHubs(); + if (connectedHubs.length == 0) { + throw new Error("No hubs are connected"); } - }; - return [connectedHubs[0], closeHubs]; + if (connectedHubs.length > 1) { + throw new Error("Multiple hubs connected. You must specify a serialNumber."); + } + + // Open the only Hub that is connected + let closeHubs = () => { + for (let hub of connectedHubs) { + hub.close(); + } + }; + return [connectedHubs[0], closeHubs]; + } } /** From d516179217f05c0d7d7e6921eb8c3c5bef70fdb5 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 15:00:54 -0500 Subject: [PATCH 51/81] depend on specific package version --- packages/control-hub/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index 44953ff6..ee636c32 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -8,7 +8,7 @@ "isomorphic-ws": "^5.0.0", "axios": "^1.4.0", "semver": "^7.5.1", - "@rev-robotics/rev-hub-core": "*" + "@rev-robotics/rev-hub-core": "^1.0.0" }, "peerDependencies": { "get-port": "6.x" From 3f1f9b70fdd65ea654f904c32d0f798a522a38b7 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 15:05:44 -0500 Subject: [PATCH 52/81] update readme --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ef8b725d..f38d12f7 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,13 @@ This project enables Node.js applications to control devices that speak the REV Hub Serial Protocol (such as the REV Robotics Expansion Hub). -## Control Hub dependencies - -The Control Hub package has two optional dependencies. - -### ws +### WiFi-control on Node.js If you are using node.js and wish to communicate with a Control Hub via WiFi, you will need to add a dependency on [ws](https://www.npmjs.com/package/ws). -### adbkit +## USB-control of Control Hub If you wish to communicate with a Control Hub over USB, you will need to set up port forwarding. This From 964d779d2d2720f7467f41df0ac8ed1cb84d6d3c Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 15:06:46 -0500 Subject: [PATCH 53/81] remove peer dependency on get-port --- package-lock.json | 7 ++----- packages/control-hub/package.json | 3 --- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 69e68b15..e2b20491 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7782,7 +7782,7 @@ "name": "@rev-robotics/control-hub", "version": "0.1.0", "dependencies": { - "@rev-robotics/rev-hub-core": "*", + "@rev-robotics/rev-hub-core": "^1.0.0", "axios": "^1.4.0", "isomorphic-ws": "^5.0.0", "semver": "^7.5.1" @@ -7792,9 +7792,6 @@ "@types/semver": "^7.5.0", "@types/ws": "^8.5.4", "typescript": "^5.0.2" - }, - "peerDependencies": { - "get-port": "6.x" } }, "packages/core": { @@ -9151,7 +9148,7 @@ "@rev-robotics/control-hub": { "version": "file:packages/control-hub", "requires": { - "@rev-robotics/rev-hub-core": "*", + "@rev-robotics/rev-hub-core": "^1.0.0", "@types/node": "^16.18.18", "@types/semver": "^7.5.0", "@types/ws": "^8.5.4", diff --git a/packages/control-hub/package.json b/packages/control-hub/package.json index ee636c32..0a419861 100644 --- a/packages/control-hub/package.json +++ b/packages/control-hub/package.json @@ -10,9 +10,6 @@ "semver": "^7.5.1", "@rev-robotics/rev-hub-core": "^1.0.0" }, - "peerDependencies": { - "get-port": "6.x" - }, "devDependencies": { "@types/node": "^16.18.18", "@types/semver": "^7.5.0", From fa8a41c45e4b4bb33e4acab57e6b51088411fc49 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 15:16:21 -0500 Subject: [PATCH 54/81] use sdkVersion field --- packages/control-hub/src/internal/ControlHub.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 91b005f2..2ac3afbb 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -159,7 +159,10 @@ export class ControlHubInternal implements ControlHub { timeout: 1000, }); if (response.data) { - let rcVersion: string = response.data.rcVersion; + let rcVersion: string | undefined = response.data.sdkVersion; + if(rcVersion === undefined) { + return false; + } return semver.satisfies(rcVersion, ">=8.2"); } From 82bba6d37f2db2870912333252de4233bce78530 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 16:07:36 -0500 Subject: [PATCH 55/81] fix motor set pid method --- packages/control-hub/src/internal/ControlHub.ts | 2 +- .../src/internal/ControlHubConnectedExpansionHub.ts | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 2ac3afbb..9338e837 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -644,6 +644,6 @@ export class ControlHubInternal implements ControlHub { setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { - return Promise.resolve(undefined); + return this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); } } diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 3a980264..77c44f62 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -564,7 +564,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setMotorPidCoefficients", { hId: this.id, c: motorChannel, - motorMode: motorMode, + m: motorMode, p: pid.p, i: pid.i, d: pid.d, @@ -685,7 +685,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return this.getMotorPIDCoefficients(motorChannel, motorMode); } - async setMotorClosedLoopControlCoefficients( motorChannel: number, motorMode: MotorMode, From d201c632c2aaa7e29e3a40dbd8741e67c4ce4d38 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 16:29:33 -0500 Subject: [PATCH 56/81] Add support for pidf --- .../control-hub/src/internal/ControlHub.ts | 4 +- .../ControlHubConnectedExpansionHub.ts | 63 ++++++++++++++++--- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 9338e837..9fc37d88 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -310,8 +310,8 @@ export class ControlHubInternal implements ControlHub { async getMotorPIDCoefficients( motorChannel: number, motorMode: number, - ): Promise { - return this.embedded.getMotorPIDCoefficients(motorChannel, motorMode); + ): Promise { + return this.embedded.getMotorPIDFCoefficients(motorChannel, motorMode); } async getMotorTargetPosition( diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 77c44f62..0a01971c 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -1,25 +1,29 @@ import { BulkInputData, - ClosedLoopControlAlgorithm, ControlHub, + ClosedLoopControlAlgorithm, + ControlHub, DebugGroup, - DigitalChannelDirection, DigitalState, + DigitalChannelDirection, + DigitalState, ExpansionHub, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, LedPattern, ModuleInterface, - ModuleStatus, MotorMode, + ModuleStatus, + MotorMode, ParentExpansionHub, ParentRevHub, - PidCoefficients, PidfCoefficients, + PidCoefficients, + PidfCoefficients, RevHub, RevHubType, Rgb, VerbosityLevel, Version, } from "@rev-robotics/rev-hub-core"; -import { EventEmitter } from "events"; +import {EventEmitter} from "events"; export class ControlHubConnectedExpansionHub implements ParentExpansionHub { isParentHub: boolean; @@ -292,6 +296,29 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } + + async getMotorPIDFCoefficients( + motorChannel: number, + motorMode: number, + ): Promise { + let result: { p: number; i: number; d: number, f: number } = await this.sendCommand( + "getMotorPidCoefficients", + { + hId: this.id, + c: motorChannel, + m: motorMode, + }, + ); + + return { + p: result.p, + i: result.i, + d: result.d, + f: result.f, + algorithm: ClosedLoopControlAlgorithm.Pidf, + }; + } + async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { @@ -571,6 +598,23 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } + + async setMotorPIDFCoefficients( + motorChannel: number, + motorMode: number, + pid: PidfCoefficients, + ): Promise { + await this.sendCommand("setMotorPidfCoefficients", { + hId: this.id, + c: motorChannel, + m: motorMode, + p: pid.p, + i: pid.i, + d: pid.d, + f: pid.f + }); + } + async setMotorTargetPosition( motorChannel: number, targetPosition_counts: number, @@ -682,7 +726,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { - return this.getMotorPIDCoefficients(motorChannel, motorMode); + return this.getMotorPIDFCoefficients(motorChannel, motorMode); } async setMotorClosedLoopControlCoefficients( @@ -691,7 +735,10 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients, ): Promise { - //Todo(landry): handle pidf - await this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + if(algorithm === ClosedLoopControlAlgorithm.Pidf) { + await this.setMotorPIDFCoefficients(motorChannel, motorMode, pid as PidfCoefficients); + } else { + await this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + } } } From 4ddbba5fb6afca237cd761a8aa49fa36fda22906 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 3 Aug 2023 16:47:33 -0500 Subject: [PATCH 57/81] fix some commands still using expansion hubs --- .../control-hub/src/internal/ControlHub.ts | 43 ++++++++++--------- .../ControlHubConnectedExpansionHub.ts | 3 +- packages/sample/src/main.ts | 28 ++++++------ 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 9fc37d88..7407388e 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -73,14 +73,19 @@ export class ControlHubInternal implements ControlHub { this.serialNumber = serialNumber; } - setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { - throw new Error("Method not implemented."); + async setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { + await this.embedded.setDigitalOutput(digitalChannel, value); } - setAllDigitalOutputs(bitPackedField: number): Promise { - throw new Error("Method not implemented."); + async setAllDigitalOutputs(bitPackedField: number): Promise { + await this.embedded.setAllDigitalOutputs(bitPackedField); } - getDigitalInput(digitalChannel: number): Promise { - throw new Error("Method not implemented."); + + getAllDigitalInputs(): Promise { + return this.embedded.getAllDigitalInputs(); + } + + async getDigitalInput(digitalChannel: number): Promise { + return await this.embedded.getDigitalInput(digitalChannel); } isParent(): this is ParentRevHub { @@ -495,6 +500,17 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); } + getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { + return this.getMotorPIDCoefficients(motorChannel, motorMode); + } + + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid, pid: PidCoefficients): Promise; + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; + setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { + return this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + } + async setNewModuleAddress(newModuleAddress: number): Promise { return this.embedded.setNewModuleAddress(newModuleAddress); } @@ -631,19 +647,4 @@ export class ControlHubInternal implements ControlHub { clearTimeout(timer); }); } - - getAllDigitalInputs(): Promise { - return Promise.resolve(0); - } - - getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { - return this.getMotorPIDCoefficients(motorChannel, motorMode); - } - - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid, pid: PidCoefficients): Promise; - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { - return this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); - } } diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 0a01971c..7e492333 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -296,13 +296,12 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } - async getMotorPIDFCoefficients( motorChannel: number, motorMode: number, ): Promise { let result: { p: number; i: number; d: number, f: number } = await this.sendCommand( - "getMotorPidCoefficients", + "getMotorPidfCoefficients", { hId: this.id, c: motorChannel, diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index b9e51ab4..01a51091 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -149,18 +149,17 @@ program }); await getLed(hub); - hub.close(); + close(); }); program .command("query ") .description("Query interface information") .action(async (name) => { - let hubs = await openConnectedExpansionHubs(); - let hub = hubs[0]; + let [hub, close] = await getRevHubOrThrow(); await queryInterface(hub, name); - hub.close(); + close(); }); program @@ -361,7 +360,7 @@ pidCommand }); await getMotorRegulatedVelocityPidf(hub, channelNumber); - hub.close(); + close(); }); let pidfCommand = motorCommand @@ -377,11 +376,11 @@ pidfCommand let iValue = Number(i); let dValue = Number(d); let fValue = Number(f); - let hubs = await openConnectedExpansionHubs(); - let hub = hubs[0]; + let [hub, close] = await getRevHubOrThrow(); + runOnSigint(() => { - hub.close(); + close(); }); await setMotorRegulatedVelocityPidf( @@ -392,7 +391,7 @@ pidfCommand dValue, fValue, ); - hub.close(); + close(); }); pidfCommand @@ -400,15 +399,14 @@ pidfCommand .description("Get PIDF coefficients for regulated velocity mode for a motor") .action(async (channel) => { let channelNumber = Number(channel); - let hubs = await openConnectedExpansionHubs(); - let hub = hubs[0]; + let [hub, close] = await getRevHubOrThrow(); runOnSigint(() => { - hub.close(); + close(); }); await getMotorRegulatedVelocityPidf(hub, channelNumber); - hub.close(); + close(); }); let alertCommand = motorCommand @@ -662,7 +660,7 @@ program }); await injectLog(hub, text); - hub.close(); + close(); }); program @@ -681,7 +679,7 @@ program let levelNumber = Number(level); await setDebugLogLevel(hub, group, levelNumber); - hub.close(); + close(); }); program From 810532f0541c1b4bd85edce8ca4b6480d4022ee1 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 4 Aug 2023 09:16:24 -0500 Subject: [PATCH 58/81] import formatting --- packages/core/src/ExpansionHub.ts | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/core/src/ExpansionHub.ts b/packages/core/src/ExpansionHub.ts index 463ba2b2..014fd515 100644 --- a/packages/core/src/ExpansionHub.ts +++ b/packages/core/src/ExpansionHub.ts @@ -1,21 +1,21 @@ import { ParentRevHub, RevHub } from "./RevHub.js"; -import {DigitalState} from "./DigitalState.js"; -import {ModuleInterface} from "./ModuleInterface.js"; -import {Rgb} from "./Rgb.js"; -import {LedPattern} from "./LedPattern.js"; -import {ModuleStatus} from "./ModuleStatus.js"; -import {DebugGroup} from "./DebugGroup.js"; -import {VerbosityLevel} from "./VerbosityLevel.js"; -import {Version} from "./Version.js"; -import {DigitalChannelDirection} from "./DigitalChannelDirection.js"; -import {I2CSpeedCode} from "./I2CSpeedCode.js"; -import {I2CWriteStatus} from "./I2CWriteStatus.js"; -import {I2CReadStatus} from "./I2CReadStatus.js"; -import {MotorMode} from "./MotorMode.js"; -import {PidCoefficients} from "./PidCoefficients.js"; -import {PidfCoefficients} from "./PidfCoefficients.js"; -import {ClosedLoopControlAlgorithm} from "./ClosedLoopControlAlgorithm.js"; -import {BulkInputData} from "./BulkInputData.js"; +import { DigitalState } from "./DigitalState.js"; +import { ModuleInterface } from "./ModuleInterface.js"; +import { Rgb } from "./Rgb.js"; +import { LedPattern } from "./LedPattern.js"; +import { ModuleStatus } from "./ModuleStatus.js"; +import { DebugGroup } from "./DebugGroup.js"; +import { VerbosityLevel } from "./VerbosityLevel.js"; +import { Version } from "./Version.js"; +import { DigitalChannelDirection } from "./DigitalChannelDirection.js"; +import { I2CSpeedCode } from "./I2CSpeedCode.js"; +import { I2CWriteStatus } from "./I2CWriteStatus.js"; +import { I2CReadStatus } from "./I2CReadStatus.js"; +import { MotorMode } from "./MotorMode.js"; +import { PidCoefficients } from "./PidCoefficients.js"; +import { PidfCoefficients } from "./PidfCoefficients.js"; +import { ClosedLoopControlAlgorithm } from "./ClosedLoopControlAlgorithm.js"; +import { BulkInputData } from "./BulkInputData.js"; export type ParentExpansionHub = ParentRevHub & ExpansionHub; From e0e75164199216936d80348f016a515566ea6696 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 4 Aug 2023 11:07:51 -0500 Subject: [PATCH 59/81] Clarify control flag --- packages/sample/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index 01a51091..e7a41b0f 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -71,7 +71,7 @@ program "communicate with the specified child Expansion Hub instead of its parent; requires parent address to be specified when the parent is an Expansion Hub", ).option( "--control", - "Specify that this hub is a control hub" + "Specify that this hub is a control hub. Default is expansion hub" ); program From 0c7ecd11f141bde01dee369e4d3c312054d7bfef Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 4 Aug 2023 15:00:11 -0500 Subject: [PATCH 60/81] get closed loop control algorithm from control hub --- .../control-hub/src/internal/ControlHub.ts | 34 ++++++------------- .../ControlHubConnectedExpansionHub.ts | 4 +-- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 7407388e..81d10a65 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -3,10 +3,11 @@ import semver from "semver"; import WebSocket from "isomorphic-ws"; import { BulkInputData, - ControlHub, ClosedLoopControlAlgorithm, - DigitalChannelDirection, DigitalState, + ControlHub, DebugGroup, + DigitalChannelDirection, + DigitalState, ExpansionHub, I2CReadStatus, I2CSpeedCode, @@ -14,17 +15,17 @@ import { LedPattern, ModuleInterface, ModuleStatus, + MotorMode, + ParentExpansionHub, ParentRevHub, PidCoefficients, + PidfCoefficients, RevHub, RevHubType, Rgb, TimeoutError, - MotorMode, - PidfCoefficients, VerbosityLevel, Version, - ParentExpansionHub, } from "@rev-robotics/rev-hub-core"; import { clearTimeout } from "timers"; import { ControlHubConnectedExpansionHub } from "./ControlHubConnectedExpansionHub.js"; @@ -312,13 +313,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getMotorEncoderPosition(motorChannel); } - async getMotorPIDCoefficients( - motorChannel: number, - motorMode: number, - ): Promise { - return this.embedded.getMotorPIDFCoefficients(motorChannel, motorMode); - } - async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { @@ -473,14 +467,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setMotorConstantPower(motorChannel, powerLevel); } - async setMotorPIDCoefficients( - motorChannel: number, - motorMode: number, - pid: PidCoefficients, - ): Promise { - return this.embedded.setMotorPIDCoefficients(motorChannel, motorMode, pid); - } - async setMotorTargetPosition( motorChannel: number, targetPosition_counts: number, @@ -500,15 +486,15 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); } - getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { - return this.getMotorPIDCoefficients(motorChannel, motorMode); + async getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { + return await this.embedded.getMotorClosedLoopControlCoefficients(motorChannel, motorMode); } setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid, pid: PidCoefficients): Promise; setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { - return this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + async setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { + return await this.embedded.setMotorClosedLoopControlCoefficients(motorChannel, motorMode, algorithm, pid); } async setNewModuleAddress(newModuleAddress: number): Promise { diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 7e492333..20adbe1a 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -300,7 +300,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { motorChannel: number, motorMode: number, ): Promise { - let result: { p: number; i: number; d: number, f: number } = await this.sendCommand( + let result: { p: number; i: number; d: number, f: number, algorithm: number } = await this.sendCommand( "getMotorPidfCoefficients", { hId: this.id, @@ -314,7 +314,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { i: result.i, d: result.d, f: result.f, - algorithm: ClosedLoopControlAlgorithm.Pidf, + algorithm: result.algorithm, }; } From 9c63babeae3330f21b0d0f62f8905e5fc8406050 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Mon, 7 Aug 2023 12:42:39 -0500 Subject: [PATCH 61/81] organize methods --- .../ControlHubConnectedExpansionHub.ts | 515 +++++++++--------- 1 file changed, 259 insertions(+), 256 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 20adbe1a..d0c45895 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -23,7 +23,7 @@ import { VerbosityLevel, Version, } from "@rev-robotics/rev-hub-core"; -import {EventEmitter} from "events"; +import { EventEmitter } from "events"; export class ControlHubConnectedExpansionHub implements ParentExpansionHub { isParentHub: boolean; @@ -60,6 +60,15 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return this.isParentHub; } + isExpansionHub(): this is ExpansionHub { + return true; + } + + isControlHub(): this is ControlHub { + //this class represents the expansion hub board, so it is not a control hub. + return false; + } + close(): void { // noinspection JSIgnoredPromiseFromCall this.sendCommand("closeHub", { @@ -167,7 +176,30 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { c: dioPin, }); - return state ? DigitalState.HIGH: DigitalState.LOW; + return state ? DigitalState.HIGH : DigitalState.LOW; + } + + async setAllDigitalOutputs(bitPackedField: number): Promise { + await this.sendCommand("readVersionString", { + hId: this.id, + bf: bitPackedField, + }); + } + + async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { + await this.sendCommand("readVersionString", { + hId: this.id, + c: dioPin, + o: direction == DigitalChannelDirection.Output, + }); + } + + async setDigitalOutput(dioPin: number, value: DigitalState): Promise { + await this.sendCommand("readVersionString", { + hId: this.id, + c: dioPin, + v: value.isHigh(), + }); } async getFTDIResetControl(): Promise { @@ -176,6 +208,20 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } + async setFTDIResetControl(_: boolean): Promise { + } + + async setI2CChannelConfiguration( + i2cChannel: number, + speedCode: I2CSpeedCode, + ): Promise { + await this.sendCommand("setI2CChannelConfiguration", { + hId: this.id, + c: i2cChannel, + sc: speedCode, + }); + } + async getI2CChannelConfiguration(i2cChannel: number): Promise { let speedCode = await this.sendCommand("getI2CChannelConfiguration", { hId: this.id, @@ -195,6 +241,44 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { throw new Error("not implemented"); } + readI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + ): Promise { + throw new Error("not implemented"); + } + + readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + throw new Error("not implemented"); + } + + writeI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + bytes: number[], + ): Promise { + throw new Error("not implemented"); + } + + writeI2CReadMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + startAddress: number, + ): Promise { + throw new Error("not implemented"); + } + + writeI2CSingleByte( + i2cChannel: number, + slaveAddress: number, + byte: number, + ): Promise { + throw new Error("not implemented"); + } + + async getInterfacePacketID( interfaceName: string, functionNumber: number, @@ -206,25 +290,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async getModuleLedColor(): Promise { - let result: { r: number; g: number; b: number } = await this.sendCommand( - "getLedColor", - { - hId: this.id, - }, - ); - - return { - red: result.r, - green: result.g, - blue: result.b, - }; - } - - getModuleLedPattern(): Promise { - throw new Error("not implemented"); - } - async getModuleStatus(_: boolean): Promise { return await this.sendCommand("getModuleStatus", { hId: this.id, @@ -275,6 +340,13 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } + async resetMotorEncoder(motorChannel: number): Promise { + await this.sendCommand("resetMotorEncoder", { + hId: this.id, + c: motorChannel, + }); + } + async getMotorPIDCoefficients( motorChannel: number, motorMode: number, @@ -342,206 +414,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async getPhoneChargeControl(): Promise { - return await this.sendCommand("getPhoneChargeControl", { - hId: this.id, - }); - } - - async getServoConfiguration(servoChannel: number): Promise { - return await this.sendCommand("getServoConfiguration", { - hId: this.id, - c: servoChannel, - }); - } - - async getServoEnable(servoChannel: number): Promise { - return await this.sendCommand("getServoEnable", { - hId: this.id, - c: servoChannel, - }); - } - - async getServoPulseWidth(servoChannel: number): Promise { - return await this.sendCommand("getServoPulseWidth", { - hId: this.id, - c: servoChannel, - }); - } - - async injectDataLogHint(hintText: string): Promise { - await this.sendCommand("injectDebugLogHint", { - hId: this.id, - hint: hintText, - }); - } - - isExpansionHub(): this is ExpansionHub { - return true; - } - - isControlHub(): this is ControlHub { - //this class represents the expansion hub board, so it is not a control hub. - return false; - } - - on( - eventName: "error" | "statusChanged" | "addressChanged" | "sessionEnded", - listener: (...param: any) => void, - ): this { - this.emitter.on(eventName, listener); - return this; - } - - async queryInterface(interfaceName: string): Promise { - let result: { name: string; firstPacketId: number; numberIds: number } = - await this.sendCommand("queryInterface", { - hId: this.id, - interfaceName: interfaceName, - }); - - return { - name: result.name, - firstPacketID: result.firstPacketId, - numberIDValues: result.numberIds, - }; - } - - readI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number, - ): Promise { - throw new Error("not implemented"); - } - - readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { - throw new Error("not implemented"); - } - - async readVersion(): Promise { - let versionString = await this.readVersionString(); - let parts = versionString.split("."); - if (parts.length != 3) { - throw new Error(`Version ${versionString} does not have 3 parts`); - } - return { - majorVersion: Number(parts[0]), - minorVersion: Number(parts[1]), - engineeringRevision: Number(parts[2]), - minorHwRevision: 0, //hardcoded in RHSPlib_device_control.c - majorHwRevision: 2, //hardcoded in RHSPlib_device_control.c - hwType: 0x311153, //hardcoded in RHSPlib_device_control.c - }; - } - - async readVersionString(): Promise { - return await this.sendCommand("readVersionString", { - hId: this.id, - }); - } - - async resetMotorEncoder(motorChannel: number): Promise { - await this.sendCommand("resetMotorEncoder", { - hId: this.id, - c: motorChannel, - }); - } - - async sendFailSafe(): Promise { - await this.sendCommand("readVersionString", { - hId: this.id, - }); - } - - async sendKeepAlive(): Promise {} - - async sendReadCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); - } - - sendWriteCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); - } - - async setDebugLogLevel( - debugGroup: DebugGroup, - verbosityLevel: VerbosityLevel, - ): Promise { - await this.sendCommand("readVersionString", { - hId: this.id, - debugGroup: debugGroup, - verbosityLevel: verbosityLevel, - }); - } - - async setAllDigitalOutputs(bitPackedField: number): Promise { - await this.sendCommand("readVersionString", { - hId: this.id, - bf: bitPackedField, - }); - } - - async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { - await this.sendCommand("readVersionString", { - hId: this.id, - c: dioPin, - o: direction == DigitalChannelDirection.Output, - }); - } - - async setDigitalOutput(dioPin: number, value: DigitalState): Promise { - await this.sendCommand("readVersionString", { - hId: this.id, - c: dioPin, - v: value.isHigh(), - }); - } - - async setFTDIResetControl(_: boolean): Promise {} - - async setI2CChannelConfiguration( - i2cChannel: number, - speedCode: I2CSpeedCode, - ): Promise { - await this.sendCommand("setI2CChannelConfiguration", { - hId: this.id, - c: i2cChannel, - sc: speedCode, - }); - } - - async setModuleLedColor(red: number, green: number, blue: number): Promise { - await this.sendCommand("setLedColor", { - hId: this.id, - r: red, - g: green, - b: blue, - }); - } - - async setModuleLedPattern(ledPattern: LedPattern): Promise { - await this.sendCommand("setLedPattern", { - hId: this.id, - s0: ledPattern.rgbtPatternStep0, - s1: ledPattern.rgbtPatternStep1, - s2: ledPattern.rgbtPatternStep2, - s3: ledPattern.rgbtPatternStep3, - s4: ledPattern.rgbtPatternStep4, - s5: ledPattern.rgbtPatternStep5, - s6: ledPattern.rgbtPatternStep6, - s7: ledPattern.rgbtPatternStep7, - s8: ledPattern.rgbtPatternStep8, - s9: ledPattern.rgbtPatternStep9, - s10: ledPattern.rgbtPatternStep10, - s11: ledPattern.rgbtPatternStep11, - s12: ledPattern.rgbtPatternStep12, - s13: ledPattern.rgbtPatternStep13, - s14: ledPattern.rgbtPatternStep14, - s15: ledPattern.rgbtPatternStep15, - }); - } - async setMotorChannelCurrentAlertLevel( motorChannel: number, currentLimit_mA: number, @@ -638,10 +510,26 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setNewModuleAddress(newModuleAddress: number): Promise { - await this.sendCommand("setNewModuleAddress", { + getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { + return this.getMotorPIDFCoefficients(motorChannel, motorMode); + } + + async setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm, + pid: PidCoefficients | PidfCoefficients, + ): Promise { + if (algorithm === ClosedLoopControlAlgorithm.Pidf) { + await this.setMotorPIDFCoefficients(motorChannel, motorMode, pid as PidfCoefficients); + } else { + await this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + } + } + + async getPhoneChargeControl(): Promise { + return await this.sendCommand("getPhoneChargeControl", { hId: this.id, - address: newModuleAddress, }); } @@ -652,6 +540,27 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } + async getServoConfiguration(servoChannel: number): Promise { + return await this.sendCommand("getServoConfiguration", { + hId: this.id, + c: servoChannel, + }); + } + + async getServoEnable(servoChannel: number): Promise { + return await this.sendCommand("getServoEnable", { + hId: this.id, + c: servoChannel, + }); + } + + async getServoPulseWidth(servoChannel: number): Promise { + return await this.sendCommand("getServoPulseWidth", { + hId: this.id, + c: servoChannel, + }); + } + async setServoConfiguration( servoChannel: number, framePeriod: number, @@ -679,31 +588,134 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - writeI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - bytes: number[], - ): Promise { - throw new Error("not implemented"); + async injectDataLogHint(hintText: string): Promise { + await this.sendCommand("injectDebugLogHint", { + hId: this.id, + hint: hintText, + }); } - writeI2CReadMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number, - startAddress: number, - ): Promise { - throw new Error("not implemented"); + async queryInterface(interfaceName: string): Promise { + let result: { name: string; firstPacketId: number; numberIds: number } = + await this.sendCommand("queryInterface", { + hId: this.id, + interfaceName: interfaceName, + }); + + return { + name: result.name, + firstPacketID: result.firstPacketId, + numberIDValues: result.numberIds, + }; } - writeI2CSingleByte( - i2cChannel: number, - slaveAddress: number, - byte: number, + async readVersion(): Promise { + let versionString = await this.readVersionString(); + let parts = versionString.split("."); + if (parts.length != 3) { + throw new Error(`Version ${versionString} does not have 3 parts`); + } + return { + majorVersion: Number(parts[0]), + minorVersion: Number(parts[1]), + engineeringRevision: Number(parts[2]), + minorHwRevision: 0, //hardcoded in RHSPlib_device_control.c + majorHwRevision: 2, //hardcoded in RHSPlib_device_control.c + hwType: 0x311153, //hardcoded in RHSPlib_device_control.c + }; + } + + async readVersionString(): Promise { + return await this.sendCommand("readVersionString", { + hId: this.id, + }); + } + + async sendFailSafe(): Promise { + await this.sendCommand("readVersionString", { + hId: this.id, + }); + } + + async sendKeepAlive(): Promise { + } + + async sendReadCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + sendWriteCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + async setDebugLogLevel( + debugGroup: DebugGroup, + verbosityLevel: VerbosityLevel, ): Promise { + await this.sendCommand("readVersionString", { + hId: this.id, + debugGroup: debugGroup, + verbosityLevel: verbosityLevel, + }); + } + + async setModuleLedColor(red: number, green: number, blue: number): Promise { + await this.sendCommand("setLedColor", { + hId: this.id, + r: red, + g: green, + b: blue, + }); + } + + async setModuleLedPattern(ledPattern: LedPattern): Promise { + await this.sendCommand("setLedPattern", { + hId: this.id, + s0: ledPattern.rgbtPatternStep0, + s1: ledPattern.rgbtPatternStep1, + s2: ledPattern.rgbtPatternStep2, + s3: ledPattern.rgbtPatternStep3, + s4: ledPattern.rgbtPatternStep4, + s5: ledPattern.rgbtPatternStep5, + s6: ledPattern.rgbtPatternStep6, + s7: ledPattern.rgbtPatternStep7, + s8: ledPattern.rgbtPatternStep8, + s9: ledPattern.rgbtPatternStep9, + s10: ledPattern.rgbtPatternStep10, + s11: ledPattern.rgbtPatternStep11, + s12: ledPattern.rgbtPatternStep12, + s13: ledPattern.rgbtPatternStep13, + s14: ledPattern.rgbtPatternStep14, + s15: ledPattern.rgbtPatternStep15, + }); + } + + async getModuleLedColor(): Promise { + let result: { r: number; g: number; b: number } = await this.sendCommand( + "getLedColor", + { + hId: this.id, + }, + ); + + return { + red: result.r, + green: result.g, + blue: result.b, + }; + } + + getModuleLedPattern(): Promise { throw new Error("not implemented"); } + async setNewModuleAddress(newModuleAddress: number): Promise { + await this.sendCommand("setNewModuleAddress", { + hId: this.id, + address: newModuleAddress, + }); + } + async addChildByAddress(moduleAddress: number): Promise { let id = await this.sendCommand("openHub", { parentSerialNumber: this.serialNumber, @@ -724,20 +736,11 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return newHub; } - getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { - return this.getMotorPIDFCoefficients(motorChannel, motorMode); - } - - async setMotorClosedLoopControlCoefficients( - motorChannel: number, - motorMode: MotorMode, - algorithm: ClosedLoopControlAlgorithm, - pid: PidCoefficients | PidfCoefficients, - ): Promise { - if(algorithm === ClosedLoopControlAlgorithm.Pidf) { - await this.setMotorPIDFCoefficients(motorChannel, motorMode, pid as PidfCoefficients); - } else { - await this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); - } + on( + eventName: "error" | "statusChanged" | "addressChanged" | "sessionEnded", + listener: (...param: any) => void, + ): this { + this.emitter.on(eventName, listener); + return this; } } From 3f58abbdad66950772dd44484a2cea7ee82733ec Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Mon, 7 Aug 2023 16:28:03 -0500 Subject: [PATCH 62/81] fix incorrect command and parameter names --- .../ControlHubConnectedExpansionHub.ts | 70 ++++++++++++------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index d0c45895..e230ae03 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -79,7 +79,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { async getAnalogInput(channel: number): Promise { return await this.sendCommand("getAnalogInput", { hId: this.id, - channel: channel, + c: channel, }); } @@ -121,7 +121,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async getServoCurrent(): Promise { - return await this.sendCommand("getMotorCurrent", { + return await this.sendCommand("getServoCurrent", { hId: this.id, }); } @@ -180,14 +180,14 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async setAllDigitalOutputs(bitPackedField: number): Promise { - await this.sendCommand("readVersionString", { + await this.sendCommand("setAllDigitalOutputs", { hId: this.id, bf: bitPackedField, }); } async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { - await this.sendCommand("readVersionString", { + await this.sendCommand("setDigitalDirection", { hId: this.id, c: dioPin, o: direction == DigitalChannelDirection.Output, @@ -195,7 +195,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async setDigitalOutput(dioPin: number, value: DigitalState): Promise { - await this.sendCommand("readVersionString", { + await this.sendCommand("setDigitalOutput", { hId: this.id, c: dioPin, v: value.isHigh(), @@ -203,9 +203,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async getFTDIResetControl(): Promise { - return await this.sendCommand("getFtdiResetControl", { - hId: this.id, - }); + return false; } async setFTDIResetControl(_: boolean): Promise { @@ -311,7 +309,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async getMotorChannelEnable(motorChannel: number): Promise { - return await this.sendCommand("getMotorChannelEnable", { + return await this.sendCommand("getMotorEnable", { hId: this.id, c: motorChannel, }); @@ -334,7 +332,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async getMotorEncoderPosition(motorChannel: number): Promise { - return await this.sendCommand("getMotorEncoderPosition", { + return await this.sendCommand("getMotorEncoder", { hId: this.id, c: motorChannel, }); @@ -438,7 +436,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { motorMode: number, floatAtZero: boolean, ): Promise { - await this.sendCommand("setMotorChannelMode", { + await this.sendCommand("setMotorMode", { hId: this.id, c: motorChannel, m: motorMode, @@ -626,33 +624,24 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async readVersionString(): Promise { - return await this.sendCommand("readVersionString", { + return await this.sendCommand("getHubFwVersionString", { hId: this.id, }); } async sendFailSafe(): Promise { - await this.sendCommand("readVersionString", { + await this.sendCommand("sendFailSafe", { hId: this.id, }); } - async sendKeepAlive(): Promise { - } - - async sendReadCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); - } - - sendWriteCommand(packetTypeID: number, payload: number[]): Promise { - return Promise.resolve([]); - } + async sendKeepAlive(): Promise {} async setDebugLogLevel( debugGroup: DebugGroup, verbosityLevel: VerbosityLevel, ): Promise { - await this.sendCommand("readVersionString", { + await this.sendCommand("setDebugLogLevel", { hId: this.id, debugGroup: debugGroup, verbosityLevel: verbosityLevel, @@ -705,8 +694,29 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } - getModuleLedPattern(): Promise { - throw new Error("not implemented"); + async getModuleLedPattern(): Promise { + let pattern: any = await this.sendCommand("getLedPattern", { + hId: this.id, + }); + + return { + rgbtPatternStep0: pattern.s0, + rgbtPatternStep1: pattern.s1, + rgbtPatternStep2: pattern.s2, + rgbtPatternStep3: pattern.s3, + rgbtPatternStep4: pattern.s4, + rgbtPatternStep5: pattern.s5, + rgbtPatternStep6: pattern.s6, + rgbtPatternStep7: pattern.s7, + rgbtPatternStep8: pattern.s8, + rgbtPatternStep9: pattern.s9, + rgbtPatternStep10: pattern.s10, + rgbtPatternStep11: pattern.s11, + rgbtPatternStep12: pattern.s12, + rgbtPatternStep13: pattern.s13, + rgbtPatternStep14: pattern.s14, + rgbtPatternStep15: pattern.s15, + }; } async setNewModuleAddress(newModuleAddress: number): Promise { @@ -743,4 +753,12 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { this.emitter.on(eventName, listener); return this; } + + sendReadCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } + + sendWriteCommand(packetTypeID: number, payload: number[]): Promise { + return Promise.resolve([]); + } } From 3c930b367e76b853ecdf92e401c6926803098285 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Mon, 7 Aug 2023 16:29:02 -0500 Subject: [PATCH 63/81] fix incorrect command and parameter names --- .../src/internal/ControlHubConnectedExpansionHub.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index e230ae03..400977e5 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -574,7 +574,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setServoEnable", { hId: this.id, c: servoChannel, - enabled: enable, + enable: enable, }); } @@ -582,7 +582,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setServoPulseWidth", { hId: this.id, c: servoChannel, - pulseWidth: pulseWidth, + pw: pulseWidth, }); } From b69da0499ecb7a20c03d1ff900f21b27e11f956c Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 9 Aug 2023 17:01:14 -0500 Subject: [PATCH 64/81] fix incorrect parameter names for motor commands --- .../internal/ControlHubConnectedExpansionHub.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 400977e5..def985b5 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -318,10 +318,14 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { async getMotorChannelMode( motorChannel: number, ): Promise<{ motorMode: number; floatAtZero: boolean }> { - return await this.sendCommand("getMotorMode", { + let result: any = await this.sendCommand("getMotorMode", { hId: this.id, c: motorChannel, }); + return { + motorMode: result.m, + floatAtZero: result.faz + } } async getMotorConstantPower(motorChannel: number): Promise { @@ -448,7 +452,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setMotorConstantPower", { hId: this.id, c: motorChannel, - motorPower: powerLevel, + p: powerLevel, }); } @@ -492,8 +496,8 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setMotorTargetPosition", { hId: this.id, c: motorChannel, - targetPositionCounts: targetPosition_counts, - targetToleranceCounts: targetTolerance_counts, + tpc: targetPosition_counts, + ttc: targetTolerance_counts, }); } @@ -504,7 +508,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setMotorTargetVelocity", { hId: this.id, c: motorChannel, - velocityCps: velocity_cps, + tv: velocity_cps, }); } From cfe620300409b5c0b222950bdfc98d12fad69d3c Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 10 Aug 2023 09:57:41 -0500 Subject: [PATCH 65/81] update parameter names for servo command --- .../control-hub/src/internal/ControlHubConnectedExpansionHub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index def985b5..7cad37a3 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -570,7 +570,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { await this.sendCommand("setServoConfiguration", { hId: this.id, c: servoChannel, - framePeriod: framePeriod, + fp: framePeriod, }); } From 75b0588deaf870d5341605ffb33471c3ec4222fd Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Thu, 10 Aug 2023 10:28:10 -0500 Subject: [PATCH 66/81] fix various incorrect parameters --- .../src/internal/ControlHubConnectedExpansionHub.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 7cad37a3..c206690d 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -108,7 +108,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async getI2CCurrent(): Promise { - return await this.sendCommand("getI2CCurrent", { + return await this.sendCommand("getI2cCurrent", { hId: this.id, }); } @@ -140,8 +140,8 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return { analog0_mV: rawData.a0, analog1_mV: rawData.a1, - analog2_mV: rawData.a3, - analog3_mV: rawData.a4, + analog2_mV: rawData.a2, + analog3_mV: rawData.a3, digitalInputs: rawData.diBf, motor0position_enc: rawData.m0ep, motor1position_enc: rawData.m1ep, From de511a4f2908fa34050591425d0db28f39a6e885 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 11:44:06 -0500 Subject: [PATCH 67/81] Add status command --- .../control-hub/src/internal/ControlHub.ts | 61 +++++++++++++++++++ .../ControlHubConnectedExpansionHub.ts | 20 ++++++ packages/sample/src/main.ts | 13 +++- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 81d10a65..98b90895 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -111,6 +111,48 @@ export class ControlHubInternal implements ControlHub { if (callback) { callback(response, error); } + } else { + //we have a message + if (rawMessage.type === "sessionEnded") { + let allHubs = this.flattenChildren(); + for (let hub of allHubs) { + hub.emit("sessionEnded"); + } + } else if (rawMessage.type === "hubAddressChanged") { + //notify that hub address changed + let payload = rawMessage.payload; + let addressChangedPayload = JSON.parse(payload); + let handles: number[] = addressChangedPayload.hIds; + + let allHubs = this.flattenChildren(); + + for (let hub of allHubs) { + if (handles.includes(hub.id)) { + hub.moduleAddress = addressChangedPayload.na; + hub.emit( + "addressChanged", + addressChangedPayload.oa, + addressChangedPayload.na, + ); + } + } + } else if (rawMessage.type === "hubStatusChanged") { + let payloadString = rawMessage.payload; + let payload = JSON.parse(payloadString); + let handles = payload.hIds; + let status: ModuleStatus = { + statusWord: payload.sBf, + motorAlerts: payload.maBf, + }; + + let allHubs = this.flattenChildren(); + + for (let hub of allHubs) { + if (handles.includes(hub.id)) { + hub.emit("statusChanged", status); + } + } + } } }); @@ -633,4 +675,23 @@ export class ControlHubInternal implements ControlHub { clearTimeout(timer); }); } + + /** + * Returns all connected hubs in the hierarchy as a flat list. Intended for + * operations that could affect all hubs. + * @private + */ + private flattenChildren(): ControlHubConnectedExpansionHub[] { + let result: ControlHubConnectedExpansionHub[] = []; + result.push(this.embedded); + + for (let child of this.children) { + if (child instanceof ControlHubConnectedExpansionHub) { + result.push(child); + result.push(...child.flattenChildren()); + } + } + + return result; + } } diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index c206690d..fafc005d 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -750,6 +750,14 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return newHub; } + emit(eventName: "error", e: Error): void; + emit(eventName: "statusChanged", status: ModuleStatus): void; + emit(eventName: "addressChanged", oldAddress: number, newAddress: number): void; + emit(eventName: "sessionEnded"): void; + emit(eventName: string, ...args: any): void { + this.emitter.emit(eventName, ...args); + } + on( eventName: "error" | "statusChanged" | "addressChanged" | "sessionEnded", listener: (...param: any) => void, @@ -765,4 +773,16 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { sendWriteCommand(packetTypeID: number, payload: number[]): Promise { return Promise.resolve([]); } + + flattenChildren(): ControlHubConnectedExpansionHub[] { + let result: ControlHubConnectedExpansionHub[] = []; + for (let child of this.children) { + if (child instanceof ControlHubConnectedExpansionHub) { + result.push(child); + result.push(...child.flattenChildren()); + } + } + + return result; + } } diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index e7a41b0f..c869e3f4 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -31,7 +31,7 @@ import { } from "@rev-robotics/expansion-hub"; import { getLed, getLedPattern, led, ledPattern } from "./command/led.js"; import { runServo } from "./command/servo.js"; -import { ExpansionHub, ParentExpansionHub, RevHub } from "@rev-robotics/rev-hub-core"; +import { ControlHub, ExpansionHub, ParentExpansionHub, RevHub } from "@rev-robotics/rev-hub-core"; import { injectLog, setDebugLogLevel } from "./command/log.js"; import { firmwareVersion } from "./command/firmware-version.js"; import { getBulkInputData } from "./command/bulkinput.js"; @@ -45,6 +45,7 @@ import { import { sendFailSafe } from "./command/failsafe.js"; import { queryInterface } from "./command/query.js"; import {openUsbControlHubs} from "./adb-setup.js"; +import { status } from "../dist/command/status.js"; function runOnSigint(block: () => void) { process.on("SIGINT", () => { @@ -698,6 +699,16 @@ program await runServo(hub, channelValue, pulseWidthValue, frameWidthValue); }); +program.command("status").action(async () => { + let [hub, close] = await getRevHubOrThrow(); + await status(hub as ControlHub); + + process.on("SIGINT", () => { + close(); + process.exit(); + }); +}); + program.parse(process.argv); /** From 70ed325ab9a925b840954fdcece78d6a0bbc82e6 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 13:24:40 -0500 Subject: [PATCH 68/81] fix ability to identify a control hub's child --- packages/sample/src/adb-setup.ts | 35 +++++++++++++++++++-- packages/sample/src/command/list.ts | 4 +-- packages/sample/src/main.ts | 48 +++++++++++++++++++++++++---- 3 files changed, 76 insertions(+), 11 deletions(-) diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index 04c678eb..ab432526 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -1,9 +1,10 @@ import { Adb, DeviceClient } from "@u4/adbkit"; import getPort from "get-port"; -import { ControlHub } from "@rev-robotics/rev-hub-core"; +import { ControlHub, ParentRevHub } from "@rev-robotics/rev-hub-core"; import { openControlHub } from "@rev-robotics/control-hub"; +import { ControlHubInternal } from "@rev-robotics/control-hub/dist/internal/ControlHub.js"; -export async function openUsbControlHubs(): Promise { +export async function openUsbControlHubsAndChildren(): Promise { let adbClient = Adb.createClient(); let controlHubs: ControlHub[] = []; @@ -15,8 +16,36 @@ export async function openUsbControlHubs(): Promise { let port = await configureHubTcp(deviceClient); let serialNumber = device.id; - let hub = await openControlHub(serialNumber, 173, port); + let hub = await openControlHub(serialNumber, 173, port) as ControlHubInternal; controlHubs.push(hub); + + let addresses: Record< + string, + { + serialNumber: string; + parentHubAddress: number; + childAddresses: number[]; + } + > = await hub.sendCommand("scanAndDiscover", {}, 20000); + + for (let serialNumber in addresses) { + let parentHub: ParentRevHub; + let childAddresses = addresses[serialNumber].childAddresses; + + if (serialNumber === "(embedded)") { + parentHub = hub; + } else { + let parentHubInfo = addresses[serialNumber]; + parentHub = await hub.addUsbConnectedHub( + serialNumber, + parentHubInfo.parentHubAddress, + ); + } + + for (let childAddress of childAddresses) { + await parentHub.addChildByAddress(childAddress); + } + } } } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 70c14dd3..961a2397 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,10 +1,10 @@ import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub"; import { controlHubHierarchyToString } from "../HubStringify.js"; import {ControlHub, ExpansionHub} from "@rev-robotics/rev-hub-core"; -import {openUsbControlHubs} from "../adb-setup.js"; +import {openUsbControlHubsAndChildren} from "../adb-setup.js"; export async function list() { - let usbControlHubs = await openUsbControlHubs(); + let usbControlHubs = await openUsbControlHubsAndChildren(); for (const hub of usbControlHubs) { let hierarchy = controlHubHierarchyToString(hub); console.log(hierarchy); diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index c869e3f4..64d468a4 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -44,8 +44,9 @@ import { } from "./command/digital.js"; import { sendFailSafe } from "./command/failsafe.js"; import { queryInterface } from "./command/query.js"; -import {openUsbControlHubs} from "./adb-setup.js"; +import {openUsbControlHubsAndChildren} from "./adb-setup.js"; import { status } from "../dist/command/status.js"; +import { setHubAddress } from "../dist/command/set-hub-address.js"; function runOnSigint(block: () => void) { process.on("SIGINT", () => { @@ -699,6 +700,16 @@ program await runServo(hub, channelValue, pulseWidthValue, frameWidthValue); }); +program + .command("set-address
") + .description("Set Module Address") + .action(async (address) => { + let addressNumber = Number(address); + let [hub, close] = await getRevHubOrThrow(); + await setHubAddress(hub as ControlHub, addressNumber); + close(); + }); + program.command("status").action(async () => { let [hub, close] = await getRevHubOrThrow(); await status(hub as ControlHub); @@ -743,8 +754,22 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void ); } if(isControlHub) { - let hubs = await openUsbControlHubs(); - return [hubs[0], () => { hubs.forEach((hub) => hub.close()) }]; + let hubs = await openUsbControlHubsAndChildren(); + let onClose = () => { hubs.forEach((hub) => hub.close()) }; + if(childAddress === undefined) { + return [hubs[0], onClose]; + } + + for(let controlHub of hubs) { + if(controlHub.moduleAddress == childAddress) { + return [controlHub as ExpansionHub, onClose]; + } + for(let hub of controlHub.children) { + if(hub.moduleAddress == childAddress) { + return [hub as ExpansionHub, onClose]; + } + } + } } else { return openExpansionHubWithSerialNumber( serialNumber, @@ -754,15 +779,26 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void } } else if (parentAddress !== undefined) { if(isControlHub) { - let hubs = await openUsbControlHubs(); - return [hubs[0], () => { hubs.forEach((hub) => hub.close()) }]; + let hubs = await openUsbControlHubsAndChildren(); + let onClose = () => { hubs.forEach((hub) => hub.close()) }; + + for(let controlHub of hubs) { + if(controlHub.moduleAddress == childAddress) { + return [controlHub as ExpansionHub, onClose]; + } + for(let hub of controlHub.children) { + if(hub.moduleAddress == childAddress) { + return [hub as ExpansionHub, onClose]; + } + } + } } else { return openExpansionHubWithAddress(parentAddress, childAddress); } } if(isControlHub) { - let hubs = await openUsbControlHubs(); + let hubs = await openUsbControlHubsAndChildren(); if (hubs.length == 0) { throw new Error("No hubs are connected"); } From 20dcd550ea1ed495f8a45286607605be1c7a9783 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 13:41:28 -0500 Subject: [PATCH 69/81] fix incorrect command name for setting hub address --- .../src/internal/ControlHubConnectedExpansionHub.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index fafc005d..9e5feca8 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -724,9 +724,9 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async setNewModuleAddress(newModuleAddress: number): Promise { - await this.sendCommand("setNewModuleAddress", { + await this.sendCommand("setHubAddress", { hId: this.id, - address: newModuleAddress, + newAddress: newModuleAddress, }); } From b8a9ec1856d513192f3360ada7e11657d17f3e58 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 14:01:53 -0500 Subject: [PATCH 70/81] pass in module address --- packages/control-hub/src/index.ts | 4 ++-- packages/control-hub/src/internal/ControlHub.ts | 5 +++-- packages/sample/src/adb-setup.ts | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/control-hub/src/index.ts b/packages/control-hub/src/index.ts index c9dbf3fb..59dcd373 100644 --- a/packages/control-hub/src/index.ts +++ b/packages/control-hub/src/index.ts @@ -1,12 +1,12 @@ import { ControlHubInternal } from "./internal/ControlHub.js"; import { ControlHub } from "@rev-robotics/rev-hub-core"; -export async function openControlHub( +export async function openWifiControlHub( serialNumber: string, moduleAddress: number, port: number, ): Promise { - let hub = new ControlHubInternal(serialNumber); + let hub = new ControlHubInternal(serialNumber, moduleAddress); await hub.open("127.0.0.1", port + 1); return hub; } diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 98b90895..e6663a50 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -32,7 +32,7 @@ import { ControlHubConnectedExpansionHub } from "./ControlHubConnectedExpansionH export class ControlHubInternal implements ControlHub { readonly isOpen: boolean = true; - readonly moduleAddress: number = 173; + readonly moduleAddress: number; responseTimeoutMs: number = 0; type: RevHubType = RevHubType.ControlHub; readonly serialNumber: string; @@ -70,8 +70,9 @@ export class ControlHubInternal implements ControlHub { (response: any | undefined, error: any | undefined) => void >(); - constructor(serialNumber: string) { + constructor(serialNumber: string, moduleAddress: number) { this.serialNumber = serialNumber; + this.moduleAddress = moduleAddress; } async setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index ab432526..23f6c81c 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -1,7 +1,7 @@ import { Adb, DeviceClient } from "@u4/adbkit"; import getPort from "get-port"; import { ControlHub, ParentRevHub } from "@rev-robotics/rev-hub-core"; -import { openControlHub } from "@rev-robotics/control-hub"; +import { openWifiControlHub } from "@rev-robotics/control-hub"; import { ControlHubInternal } from "@rev-robotics/control-hub/dist/internal/ControlHub.js"; export async function openUsbControlHubsAndChildren(): Promise { @@ -16,7 +16,7 @@ export async function openUsbControlHubsAndChildren(): Promise { let port = await configureHubTcp(deviceClient); let serialNumber = device.id; - let hub = await openControlHub(serialNumber, 173, port) as ControlHubInternal; + let hub = await openWifiControlHub(serialNumber, 173, port) as ControlHubInternal; controlHubs.push(hub); let addresses: Record< From 6d63599d97e4e7531eea064c29d946bc323f38cf Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 14:15:42 -0500 Subject: [PATCH 71/81] move digital methods and remove incorrectly named versions --- .../control-hub/src/internal/ControlHub.ts | 45 +++++++------------ 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index e6663a50..2053d4b0 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -75,21 +75,6 @@ export class ControlHubInternal implements ControlHub { this.moduleAddress = moduleAddress; } - async setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { - await this.embedded.setDigitalOutput(digitalChannel, value); - } - async setAllDigitalOutputs(bitPackedField: number): Promise { - await this.embedded.setAllDigitalOutputs(bitPackedField); - } - - getAllDigitalInputs(): Promise { - return this.embedded.getAllDigitalInputs(); - } - - async getDigitalInput(digitalChannel: number): Promise { - return await this.embedded.getDigitalInput(digitalChannel); - } - isParent(): this is ParentRevHub { return true; } @@ -287,14 +272,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getBulkInputData(); } - async getDigitalAllInputs(): Promise { - return this.embedded.getAllDigitalInputs(); - } - - async getDigitalDirection(dioPin: number): Promise { - return this.embedded.getDigitalDirection(dioPin); - } - async getFTDIResetControl(): Promise { return this.embedded.getFTDIResetControl(); } @@ -453,16 +430,28 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setDebugLogLevel(debugGroup, verbosityLevel); } - async setDigitalAllOutputs(bitPackedField: number): Promise { - return this.embedded.setAllDigitalOutputs(bitPackedField); + async getAllDigitalInputs(): Promise { + return await this.embedded.getAllDigitalInputs(); + } + + async getDigitalInput(digitalChannel: number): Promise { + return await this.embedded.getDigitalInput(digitalChannel); + } + + async getDigitalDirection(dioPin: number): Promise { + return this.embedded.getDigitalDirection(dioPin); } async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { - return this.embedded.setDigitalDirection(dioPin, direction); + return await this.embedded.setDigitalDirection(dioPin, direction); + } + + async setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { + await this.embedded.setDigitalOutput(digitalChannel, value); } - async setDigitalSingleOutput(dioPin: number, value: DigitalState): Promise { - return this.embedded.setDigitalOutput(dioPin, value); + async setAllDigitalOutputs(bitPackedField: number): Promise { + await this.embedded.setAllDigitalOutputs(bitPackedField); } async setFTDIResetControl(ftdiResetControl: boolean): Promise { From b2dd44754f8677cb2d7c5aac3419e361771b005c Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 14:33:13 -0500 Subject: [PATCH 72/81] split code for opening control hubs with children --- packages/sample/src/adb-setup.ts | 30 +----------------- packages/sample/src/command/list.ts | 4 +-- packages/sample/src/main.ts | 2 +- packages/sample/src/open-control-hub.ts | 42 +++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 32 deletions(-) create mode 100644 packages/sample/src/open-control-hub.ts diff --git a/packages/sample/src/adb-setup.ts b/packages/sample/src/adb-setup.ts index 23f6c81c..880129c0 100644 --- a/packages/sample/src/adb-setup.ts +++ b/packages/sample/src/adb-setup.ts @@ -4,7 +4,7 @@ import { ControlHub, ParentRevHub } from "@rev-robotics/rev-hub-core"; import { openWifiControlHub } from "@rev-robotics/control-hub"; import { ControlHubInternal } from "@rev-robotics/control-hub/dist/internal/ControlHub.js"; -export async function openUsbControlHubsAndChildren(): Promise { +export async function openUsbControlHubs(): Promise { let adbClient = Adb.createClient(); let controlHubs: ControlHub[] = []; @@ -18,34 +18,6 @@ export async function openUsbControlHubsAndChildren(): Promise { let hub = await openWifiControlHub(serialNumber, 173, port) as ControlHubInternal; controlHubs.push(hub); - - let addresses: Record< - string, - { - serialNumber: string; - parentHubAddress: number; - childAddresses: number[]; - } - > = await hub.sendCommand("scanAndDiscover", {}, 20000); - - for (let serialNumber in addresses) { - let parentHub: ParentRevHub; - let childAddresses = addresses[serialNumber].childAddresses; - - if (serialNumber === "(embedded)") { - parentHub = hub; - } else { - let parentHubInfo = addresses[serialNumber]; - parentHub = await hub.addUsbConnectedHub( - serialNumber, - parentHubInfo.parentHubAddress, - ); - } - - for (let childAddress of childAddresses) { - await parentHub.addChildByAddress(childAddress); - } - } } } diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index 961a2397..f30887d3 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,7 +1,7 @@ import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub"; import { controlHubHierarchyToString } from "../HubStringify.js"; -import {ControlHub, ExpansionHub} from "@rev-robotics/rev-hub-core"; -import {openUsbControlHubsAndChildren} from "../adb-setup.js"; +import {ExpansionHub} from "@rev-robotics/rev-hub-core"; +import {openUsbControlHubsAndChildren} from "../open-control-hub.js"; export async function list() { let usbControlHubs = await openUsbControlHubsAndChildren(); diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index 64d468a4..19740873 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -44,7 +44,7 @@ import { } from "./command/digital.js"; import { sendFailSafe } from "./command/failsafe.js"; import { queryInterface } from "./command/query.js"; -import {openUsbControlHubsAndChildren} from "./adb-setup.js"; +import {openUsbControlHubsAndChildren} from "./open-control-hub.js"; import { status } from "../dist/command/status.js"; import { setHubAddress } from "../dist/command/set-hub-address.js"; diff --git a/packages/sample/src/open-control-hub.ts b/packages/sample/src/open-control-hub.ts new file mode 100644 index 00000000..ec086b99 --- /dev/null +++ b/packages/sample/src/open-control-hub.ts @@ -0,0 +1,42 @@ +import { ControlHub, ParentRevHub } from "@rev-robotics/rev-hub-core"; +import { ControlHubInternal } from "@rev-robotics/control-hub/dist/internal/ControlHub.js"; +import { openUsbControlHubs } from "./adb-setup.js"; + +export async function openUsbControlHubsAndChildren(): Promise { + let hubs = await openUsbControlHubs(); + let result: ControlHub[] = []; + + for (let hub of hubs) { + let controlHub = hub as ControlHubInternal; + let addresses: Record< + string, + { + serialNumber: string; + parentHubAddress: number; + childAddresses: number[]; + } + > = await controlHub.sendCommand("scanAndDiscover", {}, 20000); + + for (let serialNumber in addresses) { + let parentHub: ParentRevHub; + let childAddresses = addresses[serialNumber].childAddresses; + + if (serialNumber === "(embedded)") { + parentHub = controlHub; + } else { + let parentHubInfo = addresses[serialNumber]; + parentHub = await controlHub.addUsbConnectedHub( + serialNumber, + parentHubInfo.parentHubAddress, + ); + } + + for (let childAddress of childAddresses) { + await parentHub.addChildByAddress(childAddress); + } + } + result.push(controlHub); + } + + return result; +} From 5aace1a6893bced35a0a90e0694b11311ccf9b29 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 14:41:06 -0500 Subject: [PATCH 73/81] formatting changes --- .../control-hub/src/internal/ControlHub.ts | 61 +++++++++--- .../ControlHubConnectedExpansionHub.ts | 41 +++++---- packages/sample/src/command/digital.ts | 2 +- packages/sample/src/main.ts | 92 +++++++++++-------- 4 files changed, 128 insertions(+), 68 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 2053d4b0..bf044c20 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -116,9 +116,9 @@ export class ControlHubInternal implements ControlHub { if (handles.includes(hub.id)) { hub.moduleAddress = addressChangedPayload.na; hub.emit( - "addressChanged", - addressChangedPayload.oa, - addressChangedPayload.na, + "addressChanged", + addressChangedPayload.oa, + addressChangedPayload.na, ); } } @@ -194,7 +194,7 @@ export class ControlHubInternal implements ControlHub { }); if (response.data) { let rcVersion: string | undefined = response.data.sdkVersion; - if(rcVersion === undefined) { + if (rcVersion === undefined) { return false; } return semver.satisfies(rcVersion, ">=8.2"); @@ -442,7 +442,10 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getDigitalDirection(dioPin); } - async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { + async setDigitalDirection( + dioPin: number, + direction: DigitalChannelDirection, + ): Promise { return await this.embedded.setDigitalDirection(dioPin, direction); } @@ -518,15 +521,49 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); } - async getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { - return await this.embedded.getMotorClosedLoopControlCoefficients(motorChannel, motorMode); + async getMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + ): Promise { + return await this.embedded.getMotorClosedLoopControlCoefficients( + motorChannel, + motorMode, + ); } - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid, pid: PidCoefficients): Promise; - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pidf, pidf: PidfCoefficients): Promise; - setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise; - async setMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode, algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf | ClosedLoopControlAlgorithm, pid: PidCoefficients | PidfCoefficients): Promise { - return await this.embedded.setMotorClosedLoopControlCoefficients(motorChannel, motorMode, algorithm, pid); + setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm.Pid, + pid: PidCoefficients, + ): Promise; + setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm.Pidf, + pidf: PidfCoefficients, + ): Promise; + setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm, + pid: PidCoefficients | PidfCoefficients, + ): Promise; + async setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: + | ClosedLoopControlAlgorithm.Pid + | ClosedLoopControlAlgorithm.Pidf + | ClosedLoopControlAlgorithm, + pid: PidCoefficients | PidfCoefficients, + ): Promise { + return await this.embedded.setMotorClosedLoopControlCoefficients( + motorChannel, + motorMode, + algorithm, + pid, + ); } async setNewModuleAddress(newModuleAddress: number): Promise { diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 9e5feca8..86e39ac4 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -186,7 +186,10 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setDigitalDirection(dioPin: number, direction: DigitalChannelDirection): Promise { + async setDigitalDirection( + dioPin: number, + direction: DigitalChannelDirection, + ): Promise { await this.sendCommand("setDigitalDirection", { hId: this.id, c: dioPin, @@ -206,8 +209,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { return false; } - async setFTDIResetControl(_: boolean): Promise { - } + async setFTDIResetControl(_: boolean): Promise {} async setI2CChannelConfiguration( i2cChannel: number, @@ -276,7 +278,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { throw new Error("not implemented"); } - async getInterfacePacketID( interfaceName: string, functionNumber: number, @@ -324,8 +325,8 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); return { motorMode: result.m, - floatAtZero: result.faz - } + floatAtZero: result.faz, + }; } async getMotorConstantPower(motorChannel: number): Promise { @@ -374,14 +375,12 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { motorChannel: number, motorMode: number, ): Promise { - let result: { p: number; i: number; d: number, f: number, algorithm: number } = await this.sendCommand( - "getMotorPidfCoefficients", - { + let result: { p: number; i: number; d: number; f: number; algorithm: number } = + await this.sendCommand("getMotorPidfCoefficients", { hId: this.id, c: motorChannel, m: motorMode, - }, - ); + }); return { p: result.p, @@ -471,7 +470,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setMotorPIDFCoefficients( motorChannel: number, motorMode: number, @@ -484,7 +482,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { p: pid.p, i: pid.i, d: pid.d, - f: pid.f + f: pid.f, }); } @@ -512,7 +510,10 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - getMotorClosedLoopControlCoefficients(motorChannel: number, motorMode: MotorMode): Promise { + getMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + ): Promise { return this.getMotorPIDFCoefficients(motorChannel, motorMode); } @@ -523,9 +524,17 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { pid: PidCoefficients | PidfCoefficients, ): Promise { if (algorithm === ClosedLoopControlAlgorithm.Pidf) { - await this.setMotorPIDFCoefficients(motorChannel, motorMode, pid as PidfCoefficients); + await this.setMotorPIDFCoefficients( + motorChannel, + motorMode, + pid as PidfCoefficients, + ); } else { - await this.setMotorPIDCoefficients(motorChannel, motorMode, pid as PidCoefficients); + await this.setMotorPIDCoefficients( + motorChannel, + motorMode, + pid as PidCoefficients, + ); } } diff --git a/packages/sample/src/command/digital.ts b/packages/sample/src/command/digital.ts index d6b35794..d8a04f2b 100644 --- a/packages/sample/src/command/digital.ts +++ b/packages/sample/src/command/digital.ts @@ -1,6 +1,6 @@ import { - DigitalState, DigitalChannelDirection, + DigitalState, ExpansionHub, } from "@rev-robotics/rev-hub-core"; diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index 19740873..cd27b447 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -1,15 +1,15 @@ import { Command } from "commander"; import { - resetEncoder, + getMotorAlertLevel_mA, + getMotorRegulatedVelocityPidf, readEncoder, + resetEncoder, runMotorConstantPower, runMotorConstantVelocity, runMotorToPosition, - setMotorRegulatedVelocityPid, setMotorAlertLevel, - getMotorAlertLevel_mA, + setMotorRegulatedVelocityPid, setMotorRegulatedVelocityPidf, - getMotorRegulatedVelocityPidf, } from "./command/motor.js"; import { analog, @@ -31,11 +31,16 @@ import { } from "@rev-robotics/expansion-hub"; import { getLed, getLedPattern, led, ledPattern } from "./command/led.js"; import { runServo } from "./command/servo.js"; -import { ControlHub, ExpansionHub, ParentExpansionHub, RevHub } from "@rev-robotics/rev-hub-core"; +import { + ControlHub, + DigitalState, + ExpansionHub, + ParentExpansionHub, + RevHub, +} from "@rev-robotics/rev-hub-core"; import { injectLog, setDebugLogLevel } from "./command/log.js"; import { firmwareVersion } from "./command/firmware-version.js"; import { getBulkInputData } from "./command/bulkinput.js"; -import { DigitalState } from "@rev-robotics/rev-hub-core"; import { digitalRead, digitalReadAll, @@ -44,7 +49,7 @@ import { } from "./command/digital.js"; import { sendFailSafe } from "./command/failsafe.js"; import { queryInterface } from "./command/query.js"; -import {openUsbControlHubsAndChildren} from "./open-control-hub.js"; +import { openUsbControlHubsAndChildren } from "./open-control-hub.js"; import { status } from "../dist/command/status.js"; import { setHubAddress } from "../dist/command/set-hub-address.js"; @@ -71,9 +76,10 @@ program .option( "-c --child
", "communicate with the specified child Expansion Hub instead of its parent; requires parent address to be specified when the parent is an Expansion Hub", - ).option( + ) + .option( "--control", - "Specify that this hub is a control hub. Default is expansion hub" + "Specify that this hub is a control hub. Default is expansion hub", ); program @@ -380,7 +386,6 @@ pidfCommand let fValue = Number(f); let [hub, close] = await getRevHubOrThrow(); - runOnSigint(() => { close(); }); @@ -701,23 +706,23 @@ program }); program - .command("set-address
") - .description("Set Module Address") - .action(async (address) => { - let addressNumber = Number(address); - let [hub, close] = await getRevHubOrThrow(); - await setHubAddress(hub as ControlHub, addressNumber); - close(); - }); + .command("set-address
") + .description("Set Module Address") + .action(async (address) => { + let addressNumber = Number(address); + let [hub, close] = await getRevHubOrThrow(); + await setHubAddress(hub as ControlHub, addressNumber); + close(); + }); program.command("status").action(async () => { - let [hub, close] = await getRevHubOrThrow(); - await status(hub as ControlHub); + let [hub, close] = await getRevHubOrThrow(); + await status(hub as ControlHub); - process.on("SIGINT", () => { - close(); - process.exit(); - }); + process.on("SIGINT", () => { + close(); + process.exit(); + }); }); program.parse(process.argv); @@ -753,19 +758,21 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void "parent address must be specified if serial number is specified.", ); } - if(isControlHub) { + if (isControlHub) { let hubs = await openUsbControlHubsAndChildren(); - let onClose = () => { hubs.forEach((hub) => hub.close()) }; - if(childAddress === undefined) { + let onClose = () => { + hubs.forEach((hub) => hub.close()); + }; + if (childAddress === undefined) { return [hubs[0], onClose]; } - for(let controlHub of hubs) { - if(controlHub.moduleAddress == childAddress) { + for (let controlHub of hubs) { + if (controlHub.moduleAddress == childAddress) { return [controlHub as ExpansionHub, onClose]; } - for(let hub of controlHub.children) { - if(hub.moduleAddress == childAddress) { + for (let hub of controlHub.children) { + if (hub.moduleAddress == childAddress) { return [hub as ExpansionHub, onClose]; } } @@ -778,16 +785,18 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void ); } } else if (parentAddress !== undefined) { - if(isControlHub) { + if (isControlHub) { let hubs = await openUsbControlHubsAndChildren(); - let onClose = () => { hubs.forEach((hub) => hub.close()) }; + let onClose = () => { + hubs.forEach((hub) => hub.close()); + }; - for(let controlHub of hubs) { - if(controlHub.moduleAddress == childAddress) { + for (let controlHub of hubs) { + if (controlHub.moduleAddress == childAddress) { return [controlHub as ExpansionHub, onClose]; } - for(let hub of controlHub.children) { - if(hub.moduleAddress == childAddress) { + for (let hub of controlHub.children) { + if (hub.moduleAddress == childAddress) { return [hub as ExpansionHub, onClose]; } } @@ -797,7 +806,7 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void } } - if(isControlHub) { + if (isControlHub) { let hubs = await openUsbControlHubsAndChildren(); if (hubs.length == 0) { throw new Error("No hubs are connected"); @@ -805,7 +814,12 @@ async function getRevHubOrThrow(): Promise<[hub: ExpansionHub, close: () => void if (hubs.length > 1) { throw new Error("Multiple hubs connected. You must specify a serialNumber."); } - return [hubs[0], () => { hubs.forEach((hub) => hub.close()) }]; + return [ + hubs[0], + () => { + hubs.forEach((hub) => hub.close()); + }, + ]; } else { let connectedHubs: ParentExpansionHub[] = await openConnectedExpansionHubs(); if (connectedHubs.length == 0) { From 41693e1d79db3cdb2e98cd84fb89d37487097585 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Fri, 11 Aug 2023 14:43:15 -0500 Subject: [PATCH 74/81] re-order methods --- .../control-hub/src/internal/ControlHub.ts | 370 +++++++-------- .../ControlHubConnectedExpansionHub.ts | 434 +++++++++--------- 2 files changed, 397 insertions(+), 407 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index bf044c20..ffeced10 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -79,6 +79,14 @@ export class ControlHubInternal implements ControlHub { return true; } + isExpansionHub(): this is ExpansionHub { + return true; + } + + isControlHub(): this is ControlHub { + return true; + } + async open(ip: string, port: number): Promise { this.webSocketConnection = new WebSocket(`ws://${ip}:${port}`); @@ -276,16 +284,8 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getFTDIResetControl(); } - async getI2CChannelConfiguration(i2cChannel: number): Promise { - return this.embedded.getI2CChannelConfiguration(i2cChannel); - } - - getI2CReadStatus(i2cChannel: number): Promise { - return this.embedded.getI2CReadStatus(i2cChannel); - } - - getI2CWriteStatus(i2cChannel: number): Promise { - return this.embedded.getI2CWriteStatus(i2cChannel); + async setFTDIResetControl(ftdiResetControl: boolean): Promise { + return this.embedded.setFTDIResetControl(ftdiResetControl); } async getInterfacePacketID( @@ -295,14 +295,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getInterfacePacketID(interfaceName, functionNumber); } - async getModuleLedColor(): Promise { - return this.embedded.getModuleLedColor(); - } - - getModuleLedPattern(): Promise { - return this.embedded.getModuleLedPattern(); - } - async getModuleStatus(clearStatusAfterResponse: boolean): Promise { return this.embedded.getModuleStatus(clearStatusAfterResponse); } @@ -311,10 +303,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getMotorAtTarget(motorChannel); } - async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { - return this.embedded.getMotorChannelCurrentAlertLevel(motorChannel); - } - async getMotorChannelEnable(motorChannel: number): Promise { return this.embedded.getMotorChannelEnable(motorChannel); } @@ -325,22 +313,120 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getMotorChannelMode(motorChannel); } - async getMotorConstantPower(motorChannel: number): Promise { - return this.embedded.getMotorConstantPower(motorChannel); + async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { + return this.embedded.getMotorChannelCurrentAlertLevel(motorChannel); } async getMotorEncoderPosition(motorChannel: number): Promise { return this.embedded.getMotorEncoderPosition(motorChannel); } + async getMotorConstantPower(motorChannel: number): Promise { + return this.embedded.getMotorConstantPower(motorChannel); + } + + async getMotorTargetVelocity(motorChannel: number): Promise { + return this.embedded.getMotorTargetVelocity(motorChannel); + } + async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { return this.embedded.getMotorTargetPosition(motorChannel); } - async getMotorTargetVelocity(motorChannel: number): Promise { - return this.embedded.getMotorTargetVelocity(motorChannel); + async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { + return this.embedded.setMotorChannelEnable(motorChannel, enable); + } + + async setMotorChannelMode( + motorChannel: number, + motorMode: number, + floatAtZero: boolean, + ): Promise { + return this.embedded.setMotorChannelMode(motorChannel, motorMode, floatAtZero); + } + + async setMotorChannelCurrentAlertLevel( + motorChannel: number, + currentLimit_mA: number, + ): Promise { + return this.embedded.setMotorChannelCurrentAlertLevel( + motorChannel, + currentLimit_mA, + ); + } + + async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { + return this.embedded.setMotorConstantPower(motorChannel, powerLevel); + } + + async setMotorTargetVelocity( + motorChannel: number, + velocity_cps: number, + ): Promise { + return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); + } + + async setMotorTargetPosition( + motorChannel: number, + targetPosition_counts: number, + targetTolerance_counts: number, + ): Promise { + return this.embedded.setMotorTargetPosition( + motorChannel, + targetPosition_counts, + targetTolerance_counts, + ); + } + + async getMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + ): Promise { + return await this.embedded.getMotorClosedLoopControlCoefficients( + motorChannel, + motorMode, + ); + } + + setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm.Pid, + pid: PidCoefficients, + ): Promise; + + setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm.Pidf, + pidf: PidfCoefficients, + ): Promise; + + setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm, + pid: PidCoefficients | PidfCoefficients, + ): Promise; + + async setMotorClosedLoopControlCoefficients( + motorChannel: number, + motorMode: MotorMode, + algorithm: ClosedLoopControlAlgorithm.Pid | ClosedLoopControlAlgorithm.Pidf, + pid: PidCoefficients | PidfCoefficients, + ): Promise { + return await this.embedded.setMotorClosedLoopControlCoefficients( + motorChannel, + motorMode, + algorithm, + pid, + ); + } + + async resetMotorEncoder(motorChannel: number): Promise { + return this.embedded.resetMotorEncoder(motorChannel); } async getPhoneChargeControl(): Promise { @@ -363,20 +449,27 @@ export class ControlHubInternal implements ControlHub { return this.embedded.injectDataLogHint(hintText); } - isExpansionHub(): this is ExpansionHub { - return true; + async queryInterface(interfaceName: string): Promise { + return this.embedded.queryInterface(interfaceName); } - isControlHub(): this is ControlHub { - return true; + async getI2CChannelConfiguration(i2cChannel: number): Promise { + return this.embedded.getI2CChannelConfiguration(i2cChannel); } - on(eventName: "error", listener: (error: Error) => void): RevHub { - return this.embedded.on(eventName, listener); + getI2CReadStatus(i2cChannel: number): Promise { + return this.embedded.getI2CReadStatus(i2cChannel); } - async queryInterface(interfaceName: string): Promise { - return this.embedded.queryInterface(interfaceName); + getI2CWriteStatus(i2cChannel: number): Promise { + return this.embedded.getI2CWriteStatus(i2cChannel); + } + + async setI2CChannelConfiguration( + i2cChannel: number, + speedCode: I2CSpeedCode, + ): Promise { + return this.embedded.setI2CChannelConfiguration(i2cChannel, speedCode); } readI2CMultipleBytes( @@ -391,8 +484,38 @@ export class ControlHubInternal implements ControlHub { ); } - readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { - return this.embedded.readI2CSingleByte(i2cChannel, slaveAddress); + async readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + return await this.embedded.readI2CSingleByte(i2cChannel, slaveAddress); + } + + async writeI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + bytes: number[], + ): Promise { + return await this.embedded.writeI2CMultipleBytes(i2cChannel, slaveAddress, bytes); + } + + async writeI2CReadMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + startAddress: number, + ): Promise { + return await this.embedded.writeI2CReadMultipleBytes( + i2cChannel, + slaveAddress, + numBytesToRead, + startAddress, + ); + } + + async writeI2CSingleByte( + i2cChannel: number, + slaveAddress: number, + byte: number, + ): Promise { + return await this.embedded.writeI2CSingleByte(i2cChannel, slaveAddress, byte); } async readVersion(): Promise { @@ -403,10 +526,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.readVersionString(); } - async resetMotorEncoder(motorChannel: number): Promise { - return this.embedded.resetMotorEncoder(motorChannel); - } - async sendFailSafe(): Promise { return this.embedded.sendFailSafe(); } @@ -415,14 +534,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.sendKeepAlive(); } - async sendReadCommand(packetTypeID: number, payload: number[]): Promise { - return this.embedded.sendReadCommand(packetTypeID, payload); - } - - sendWriteCommand(packetTypeID: number, payload: number[]): Promise { - return this.embedded.sendWriteCommand(packetTypeID, payload); - } - async setDebugLogLevel( debugGroup: DebugGroup, verbosityLevel: VerbosityLevel, @@ -442,30 +553,27 @@ export class ControlHubInternal implements ControlHub { return this.embedded.getDigitalDirection(dioPin); } - async setDigitalDirection( - dioPin: number, - direction: DigitalChannelDirection, - ): Promise { - return await this.embedded.setDigitalDirection(dioPin, direction); + async setAllDigitalOutputs(bitPackedField: number): Promise { + await this.embedded.setAllDigitalOutputs(bitPackedField); } async setDigitalOutput(digitalChannel: number, value: DigitalState): Promise { await this.embedded.setDigitalOutput(digitalChannel, value); } - async setAllDigitalOutputs(bitPackedField: number): Promise { - await this.embedded.setAllDigitalOutputs(bitPackedField); + async setDigitalDirection( + dioPin: number, + direction: DigitalChannelDirection, + ): Promise { + return await this.embedded.setDigitalDirection(dioPin, direction); } - async setFTDIResetControl(ftdiResetControl: boolean): Promise { - return this.embedded.setFTDIResetControl(ftdiResetControl); + async getModuleLedColor(): Promise { + return this.embedded.getModuleLedColor(); } - async setI2CChannelConfiguration( - i2cChannel: number, - speedCode: I2CSpeedCode, - ): Promise { - return this.embedded.setI2CChannelConfiguration(i2cChannel, speedCode); + getModuleLedPattern(): Promise { + return this.embedded.getModuleLedPattern(); } async setModuleLedColor(red: number, green: number, blue: number): Promise { @@ -476,95 +584,6 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setModuleLedPattern(ledPattern); } - async setMotorChannelCurrentAlertLevel( - motorChannel: number, - currentLimit_mA: number, - ): Promise { - return this.embedded.setMotorChannelCurrentAlertLevel( - motorChannel, - currentLimit_mA, - ); - } - - async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { - return this.embedded.setMotorChannelEnable(motorChannel, enable); - } - - async setMotorChannelMode( - motorChannel: number, - motorMode: number, - floatAtZero: boolean, - ): Promise { - return this.embedded.setMotorChannelMode(motorChannel, motorMode, floatAtZero); - } - - async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { - return this.embedded.setMotorConstantPower(motorChannel, powerLevel); - } - - async setMotorTargetPosition( - motorChannel: number, - targetPosition_counts: number, - targetTolerance_counts: number, - ): Promise { - return this.embedded.setMotorTargetPosition( - motorChannel, - targetPosition_counts, - targetTolerance_counts, - ); - } - - async setMotorTargetVelocity( - motorChannel: number, - velocity_cps: number, - ): Promise { - return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); - } - - async getMotorClosedLoopControlCoefficients( - motorChannel: number, - motorMode: MotorMode, - ): Promise { - return await this.embedded.getMotorClosedLoopControlCoefficients( - motorChannel, - motorMode, - ); - } - - setMotorClosedLoopControlCoefficients( - motorChannel: number, - motorMode: MotorMode, - algorithm: ClosedLoopControlAlgorithm.Pid, - pid: PidCoefficients, - ): Promise; - setMotorClosedLoopControlCoefficients( - motorChannel: number, - motorMode: MotorMode, - algorithm: ClosedLoopControlAlgorithm.Pidf, - pidf: PidfCoefficients, - ): Promise; - setMotorClosedLoopControlCoefficients( - motorChannel: number, - motorMode: MotorMode, - algorithm: ClosedLoopControlAlgorithm, - pid: PidCoefficients | PidfCoefficients, - ): Promise; - async setMotorClosedLoopControlCoefficients( - motorChannel: number, - motorMode: MotorMode, - algorithm: - | ClosedLoopControlAlgorithm.Pid - | ClosedLoopControlAlgorithm.Pidf - | ClosedLoopControlAlgorithm, - pid: PidCoefficients | PidfCoefficients, - ): Promise { - return await this.embedded.setMotorClosedLoopControlCoefficients( - motorChannel, - motorMode, - algorithm, - pid, - ); - } async setNewModuleAddress(newModuleAddress: number): Promise { return this.embedded.setNewModuleAddress(newModuleAddress); @@ -589,34 +608,19 @@ export class ControlHubInternal implements ControlHub { return this.embedded.setServoPulseWidth(servoChannel, pulseWidth); } - writeI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - bytes: number[], - ): Promise { - return this.embedded.writeI2CMultipleBytes(i2cChannel, slaveAddress, bytes); - } - - writeI2CReadMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number, - startAddress: number, - ): Promise { - return this.embedded.writeI2CReadMultipleBytes( - i2cChannel, - slaveAddress, - numBytesToRead, - startAddress, - ); - } - - writeI2CSingleByte( - i2cChannel: number, - slaveAddress: number, - byte: number, - ): Promise { - return this.embedded.writeI2CSingleByte(i2cChannel, slaveAddress, byte); + on(eventName: "error", listener: (error: Error) => void): this; + on(eventName: "statusChanged", listener: (status: ModuleStatus) => void): this; + on( + eventName: "addressChanged", + listener: (oldAddress: number, newAddress: number) => void, + ): this; + on(eventName: "sessionEnded", listener: () => void): this; + on( + eventName: "error" | "statusChanged" | "addressChanged" | "sessionEnded", + listener: (...args: any) => void, + ): this { + this.embedded.on(eventName, listener); + return this; } async addChildByAddress(moduleAddress: number): Promise { @@ -703,6 +707,14 @@ export class ControlHubInternal implements ControlHub { }); } + async sendReadCommand(packetTypeID: number, payload: number[]): Promise { + return this.embedded.sendReadCommand(packetTypeID, payload); + } + + sendWriteCommand(packetTypeID: number, payload: number[]): Promise { + return this.embedded.sendWriteCommand(packetTypeID, payload); + } + /** * Returns all connected hubs in the hierarchy as a flat list. Intended for * operations that could affect all hubs. diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 86e39ac4..0bd99298 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -155,129 +155,12 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } - async getAllDigitalInputs(): Promise { - return await this.sendCommand("getAllDigitalInputs", { - hId: this.id, - }); - } - - async getDigitalDirection(dioPin: number): Promise { - let isOutput = await this.sendCommand("getDigitalDirection", { - hId: this.id, - channel: dioPin, - }); - - return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; - } - - async getDigitalInput(dioPin: number): Promise { - let state: boolean = await this.sendCommand("getDigitalInput", { - hId: this.id, - c: dioPin, - }); - - return state ? DigitalState.HIGH : DigitalState.LOW; - } - - async setAllDigitalOutputs(bitPackedField: number): Promise { - await this.sendCommand("setAllDigitalOutputs", { - hId: this.id, - bf: bitPackedField, - }); - } - - async setDigitalDirection( - dioPin: number, - direction: DigitalChannelDirection, - ): Promise { - await this.sendCommand("setDigitalDirection", { - hId: this.id, - c: dioPin, - o: direction == DigitalChannelDirection.Output, - }); - } - - async setDigitalOutput(dioPin: number, value: DigitalState): Promise { - await this.sendCommand("setDigitalOutput", { - hId: this.id, - c: dioPin, - v: value.isHigh(), - }); - } - async getFTDIResetControl(): Promise { return false; } async setFTDIResetControl(_: boolean): Promise {} - async setI2CChannelConfiguration( - i2cChannel: number, - speedCode: I2CSpeedCode, - ): Promise { - await this.sendCommand("setI2CChannelConfiguration", { - hId: this.id, - c: i2cChannel, - sc: speedCode, - }); - } - - async getI2CChannelConfiguration(i2cChannel: number): Promise { - let speedCode = await this.sendCommand("getI2CChannelConfiguration", { - hId: this.id, - c: i2cChannel, - }); - - return speedCode == 1 - ? I2CSpeedCode.SpeedCode400_Kbps - : I2CSpeedCode.SpeedCode100_Kbps; - } - - getI2CReadStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); - } - - getI2CWriteStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); - } - - readI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number, - ): Promise { - throw new Error("not implemented"); - } - - readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { - throw new Error("not implemented"); - } - - writeI2CMultipleBytes( - i2cChannel: number, - slaveAddress: number, - bytes: number[], - ): Promise { - throw new Error("not implemented"); - } - - writeI2CReadMultipleBytes( - i2cChannel: number, - slaveAddress: number, - numBytesToRead: number, - startAddress: number, - ): Promise { - throw new Error("not implemented"); - } - - writeI2CSingleByte( - i2cChannel: number, - slaveAddress: number, - byte: number, - ): Promise { - throw new Error("not implemented"); - } - async getInterfacePacketID( interfaceName: string, functionNumber: number, @@ -302,13 +185,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { - return await this.sendCommand("getMotorAlertLevel", { - hId: this.id, - c: motorChannel, - }); - } - async getMotorChannelEnable(motorChannel: number): Promise { return await this.sendCommand("getMotorEnable", { hId: this.id, @@ -329,8 +205,8 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } - async getMotorConstantPower(motorChannel: number): Promise { - return await this.sendCommand("getMotorConstantPower", { + async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { + return await this.sendCommand("getMotorAlertLevel", { hId: this.id, c: motorChannel, }); @@ -343,52 +219,18 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async resetMotorEncoder(motorChannel: number): Promise { - await this.sendCommand("resetMotorEncoder", { + async getMotorConstantPower(motorChannel: number): Promise { + return await this.sendCommand("getMotorConstantPower", { hId: this.id, c: motorChannel, }); } - async getMotorPIDCoefficients( - motorChannel: number, - motorMode: number, - ): Promise { - let result: { p: number; i: number; d: number } = await this.sendCommand( - "getMotorPidCoefficients", - { - hId: this.id, - c: motorChannel, - m: motorMode, - }, - ); - - return { - p: result.p, - i: result.i, - d: result.d, - algorithm: ClosedLoopControlAlgorithm.Pid, - }; - } - - async getMotorPIDFCoefficients( - motorChannel: number, - motorMode: number, - ): Promise { - let result: { p: number; i: number; d: number; f: number; algorithm: number } = - await this.sendCommand("getMotorPidfCoefficients", { - hId: this.id, - c: motorChannel, - m: motorMode, - }); - - return { - p: result.p, - i: result.i, - d: result.d, - f: result.f, - algorithm: result.algorithm, - }; + async getMotorTargetVelocity(motorChannel: number): Promise { + return await this.sendCommand("getMotorTargetVelocity", { + hId: this.id, + c: motorChannel, + }); } async getMotorTargetPosition( @@ -408,10 +250,24 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } - async getMotorTargetVelocity(motorChannel: number): Promise { - return await this.sendCommand("getMotorTargetVelocity", { + async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { + await this.sendCommand("setMotorEnabled", { hId: this.id, c: motorChannel, + enable: enable, + }); + } + + async setMotorChannelMode( + motorChannel: number, + motorMode: number, + floatAtZero: boolean, + ): Promise { + await this.sendCommand("setMotorMode", { + hId: this.id, + c: motorChannel, + m: motorMode, + faz: floatAtZero, }); } @@ -426,35 +282,58 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { - await this.sendCommand("setMotorEnabled", { + async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { + await this.sendCommand("setMotorConstantPower", { hId: this.id, c: motorChannel, - enable: enable, + p: powerLevel, }); } - async setMotorChannelMode( + async setMotorTargetVelocity( motorChannel: number, - motorMode: number, - floatAtZero: boolean, + velocity_cps: number, ): Promise { - await this.sendCommand("setMotorMode", { + await this.sendCommand("setMotorTargetVelocity", { hId: this.id, c: motorChannel, - m: motorMode, - faz: floatAtZero, + tv: velocity_cps, }); } - async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { - await this.sendCommand("setMotorConstantPower", { + async setMotorTargetPosition( + motorChannel: number, + targetPosition_counts: number, + targetTolerance_counts: number, + ): Promise { + await this.sendCommand("setMotorTargetPosition", { hId: this.id, c: motorChannel, - p: powerLevel, + tpc: targetPosition_counts, + ttc: targetTolerance_counts, }); } + async getMotorPIDFCoefficients( + motorChannel: number, + motorMode: number, + ): Promise { + let result: { p: number; i: number; d: number; f: number; algorithm: number } = + await this.sendCommand("getMotorPidfCoefficients", { + hId: this.id, + c: motorChannel, + m: motorMode, + }); + + return { + p: result.p, + i: result.i, + d: result.d, + f: result.f, + algorithm: result.algorithm, + }; + } + async setMotorPIDCoefficients( motorChannel: number, motorMode: number, @@ -486,30 +365,6 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setMotorTargetPosition( - motorChannel: number, - targetPosition_counts: number, - targetTolerance_counts: number, - ): Promise { - await this.sendCommand("setMotorTargetPosition", { - hId: this.id, - c: motorChannel, - tpc: targetPosition_counts, - ttc: targetTolerance_counts, - }); - } - - async setMotorTargetVelocity( - motorChannel: number, - velocity_cps: number, - ): Promise { - await this.sendCommand("setMotorTargetVelocity", { - hId: this.id, - c: motorChannel, - tv: velocity_cps, - }); - } - getMotorClosedLoopControlCoefficients( motorChannel: number, motorMode: MotorMode, @@ -538,6 +393,13 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } } + async resetMotorEncoder(motorChannel: number): Promise { + await this.sendCommand("resetMotorEncoder", { + hId: this.id, + c: motorChannel, + }); + } + async getPhoneChargeControl(): Promise { return await this.sendCommand("getPhoneChargeControl", { hId: this.id, @@ -619,6 +481,72 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { numberIDValues: result.numberIds, }; } + async setI2CChannelConfiguration( + i2cChannel: number, + speedCode: I2CSpeedCode, + ): Promise { + await this.sendCommand("setI2CChannelConfiguration", { + hId: this.id, + c: i2cChannel, + sc: speedCode, + }); + } + + async getI2CChannelConfiguration(i2cChannel: number): Promise { + let speedCode = await this.sendCommand("getI2CChannelConfiguration", { + hId: this.id, + c: i2cChannel, + }); + + return speedCode == 1 + ? I2CSpeedCode.SpeedCode400_Kbps + : I2CSpeedCode.SpeedCode100_Kbps; + } + + getI2CReadStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + getI2CWriteStatus(i2cChannel: number): Promise { + throw new Error("not implemented"); + } + + readI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + ): Promise { + throw new Error("not implemented"); + } + + readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + throw new Error("not implemented"); + } + + writeI2CMultipleBytes( + i2cChannel: number, + slaveAddress: number, + bytes: number[], + ): Promise { + throw new Error("not implemented"); + } + + writeI2CReadMultipleBytes( + i2cChannel: number, + slaveAddress: number, + numBytesToRead: number, + startAddress: number, + ): Promise { + throw new Error("not implemented"); + } + + writeI2CSingleByte( + i2cChannel: number, + slaveAddress: number, + byte: number, + ): Promise { + throw new Error("not implemented"); + } async readVersion(): Promise { let versionString = await this.readVersionString(); @@ -661,34 +589,53 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }); } - async setModuleLedColor(red: number, green: number, blue: number): Promise { - await this.sendCommand("setLedColor", { + async getAllDigitalInputs(): Promise { + return await this.sendCommand("getAllDigitalInputs", { hId: this.id, - r: red, - g: green, - b: blue, }); } - async setModuleLedPattern(ledPattern: LedPattern): Promise { - await this.sendCommand("setLedPattern", { + async getDigitalInput(dioPin: number): Promise { + let state: boolean = await this.sendCommand("getDigitalInput", { hId: this.id, - s0: ledPattern.rgbtPatternStep0, - s1: ledPattern.rgbtPatternStep1, - s2: ledPattern.rgbtPatternStep2, - s3: ledPattern.rgbtPatternStep3, - s4: ledPattern.rgbtPatternStep4, - s5: ledPattern.rgbtPatternStep5, - s6: ledPattern.rgbtPatternStep6, - s7: ledPattern.rgbtPatternStep7, - s8: ledPattern.rgbtPatternStep8, - s9: ledPattern.rgbtPatternStep9, - s10: ledPattern.rgbtPatternStep10, - s11: ledPattern.rgbtPatternStep11, - s12: ledPattern.rgbtPatternStep12, - s13: ledPattern.rgbtPatternStep13, - s14: ledPattern.rgbtPatternStep14, - s15: ledPattern.rgbtPatternStep15, + c: dioPin, + }); + + return state ? DigitalState.HIGH : DigitalState.LOW; + } + + async getDigitalDirection(dioPin: number): Promise { + let isOutput = await this.sendCommand("getDigitalDirection", { + hId: this.id, + channel: dioPin, + }); + + return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; + } + + async setAllDigitalOutputs(bitPackedField: number): Promise { + await this.sendCommand("setAllDigitalOutputs", { + hId: this.id, + bf: bitPackedField, + }); + } + + async setDigitalOutput(dioPin: number, value: DigitalState): Promise { + await this.sendCommand("setDigitalOutput", { + hId: this.id, + c: dioPin, + v: value.isHigh(), + }); + } + + async setDigitalDirection( + dioPin: number, + direction: DigitalChannelDirection, + ): Promise { + await this.sendCommand("setDigitalDirection", { + hId: this.id, + c: dioPin, + o: direction == DigitalChannelDirection.Output, }); } @@ -732,6 +679,37 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { }; } + async setModuleLedColor(red: number, green: number, blue: number): Promise { + await this.sendCommand("setLedColor", { + hId: this.id, + r: red, + g: green, + b: blue, + }); + } + + async setModuleLedPattern(ledPattern: LedPattern): Promise { + await this.sendCommand("setLedPattern", { + hId: this.id, + s0: ledPattern.rgbtPatternStep0, + s1: ledPattern.rgbtPatternStep1, + s2: ledPattern.rgbtPatternStep2, + s3: ledPattern.rgbtPatternStep3, + s4: ledPattern.rgbtPatternStep4, + s5: ledPattern.rgbtPatternStep5, + s6: ledPattern.rgbtPatternStep6, + s7: ledPattern.rgbtPatternStep7, + s8: ledPattern.rgbtPatternStep8, + s9: ledPattern.rgbtPatternStep9, + s10: ledPattern.rgbtPatternStep10, + s11: ledPattern.rgbtPatternStep11, + s12: ledPattern.rgbtPatternStep12, + s13: ledPattern.rgbtPatternStep13, + s14: ledPattern.rgbtPatternStep14, + s15: ledPattern.rgbtPatternStep15, + }); + } + async setNewModuleAddress(newModuleAddress: number): Promise { await this.sendCommand("setHubAddress", { hId: this.id, From 033ac2702880da5513859dc8569694a9ebcff435 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Tue, 15 Aug 2023 12:49:36 -0500 Subject: [PATCH 75/81] add await where missing --- .../control-hub/src/internal/ControlHub.ts | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index ffeced10..5fd289c2 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -296,47 +296,47 @@ export class ControlHubInternal implements ControlHub { } async getModuleStatus(clearStatusAfterResponse: boolean): Promise { - return this.embedded.getModuleStatus(clearStatusAfterResponse); + return await this.embedded.getModuleStatus(clearStatusAfterResponse); } async getMotorAtTarget(motorChannel: number): Promise { - return this.embedded.getMotorAtTarget(motorChannel); + return await this.embedded.getMotorAtTarget(motorChannel); } async getMotorChannelEnable(motorChannel: number): Promise { - return this.embedded.getMotorChannelEnable(motorChannel); + return await this.embedded.getMotorChannelEnable(motorChannel); } async getMotorChannelMode( motorChannel: number, ): Promise<{ motorMode: number; floatAtZero: boolean }> { - return this.embedded.getMotorChannelMode(motorChannel); + return await this.embedded.getMotorChannelMode(motorChannel); } async getMotorChannelCurrentAlertLevel(motorChannel: number): Promise { - return this.embedded.getMotorChannelCurrentAlertLevel(motorChannel); + return await this.embedded.getMotorChannelCurrentAlertLevel(motorChannel); } async getMotorEncoderPosition(motorChannel: number): Promise { - return this.embedded.getMotorEncoderPosition(motorChannel); + return await this.embedded.getMotorEncoderPosition(motorChannel); } async getMotorConstantPower(motorChannel: number): Promise { - return this.embedded.getMotorConstantPower(motorChannel); + return await this.embedded.getMotorConstantPower(motorChannel); } async getMotorTargetVelocity(motorChannel: number): Promise { - return this.embedded.getMotorTargetVelocity(motorChannel); + return await this.embedded.getMotorTargetVelocity(motorChannel); } async getMotorTargetPosition( motorChannel: number, ): Promise<{ targetPosition: number; targetTolerance: number }> { - return this.embedded.getMotorTargetPosition(motorChannel); + return await this.embedded.getMotorTargetPosition(motorChannel); } async setMotorChannelEnable(motorChannel: number, enable: boolean): Promise { - return this.embedded.setMotorChannelEnable(motorChannel, enable); + return await this.embedded.setMotorChannelEnable(motorChannel, enable); } async setMotorChannelMode( @@ -344,28 +344,28 @@ export class ControlHubInternal implements ControlHub { motorMode: number, floatAtZero: boolean, ): Promise { - return this.embedded.setMotorChannelMode(motorChannel, motorMode, floatAtZero); + return await this.embedded.setMotorChannelMode(motorChannel, motorMode, floatAtZero); } async setMotorChannelCurrentAlertLevel( motorChannel: number, currentLimit_mA: number, ): Promise { - return this.embedded.setMotorChannelCurrentAlertLevel( + return await this.embedded.setMotorChannelCurrentAlertLevel( motorChannel, currentLimit_mA, ); } async setMotorConstantPower(motorChannel: number, powerLevel: number): Promise { - return this.embedded.setMotorConstantPower(motorChannel, powerLevel); + return await this.embedded.setMotorConstantPower(motorChannel, powerLevel); } async setMotorTargetVelocity( motorChannel: number, velocity_cps: number, ): Promise { - return this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); + return await this.embedded.setMotorTargetVelocity(motorChannel, velocity_cps); } async setMotorTargetPosition( @@ -373,7 +373,7 @@ export class ControlHubInternal implements ControlHub { targetPosition_counts: number, targetTolerance_counts: number, ): Promise { - return this.embedded.setMotorTargetPosition( + return await this.embedded.setMotorTargetPosition( motorChannel, targetPosition_counts, targetTolerance_counts, @@ -426,58 +426,58 @@ export class ControlHubInternal implements ControlHub { } async resetMotorEncoder(motorChannel: number): Promise { - return this.embedded.resetMotorEncoder(motorChannel); + return await this.embedded.resetMotorEncoder(motorChannel); } async getPhoneChargeControl(): Promise { - return this.embedded.getPhoneChargeControl(); + return await this.embedded.getPhoneChargeControl(); } async getServoConfiguration(servoChannel: number): Promise { - return this.embedded.getServoConfiguration(servoChannel); + return await this.embedded.getServoConfiguration(servoChannel); } async getServoEnable(servoChannel: number): Promise { - return this.embedded.getServoEnable(servoChannel); + return await this.embedded.getServoEnable(servoChannel); } async getServoPulseWidth(servoChannel: number): Promise { - return this.embedded.getServoPulseWidth(servoChannel); + return await this.embedded.getServoPulseWidth(servoChannel); } async injectDataLogHint(hintText: string): Promise { - return this.embedded.injectDataLogHint(hintText); + return await this.embedded.injectDataLogHint(hintText); } async queryInterface(interfaceName: string): Promise { - return this.embedded.queryInterface(interfaceName); + return await this.embedded.queryInterface(interfaceName); } async getI2CChannelConfiguration(i2cChannel: number): Promise { - return this.embedded.getI2CChannelConfiguration(i2cChannel); + return await this.embedded.getI2CChannelConfiguration(i2cChannel); } - getI2CReadStatus(i2cChannel: number): Promise { - return this.embedded.getI2CReadStatus(i2cChannel); + async getI2CReadStatus(i2cChannel: number): Promise { + return await this.embedded.getI2CReadStatus(i2cChannel); } - getI2CWriteStatus(i2cChannel: number): Promise { - return this.embedded.getI2CWriteStatus(i2cChannel); + async getI2CWriteStatus(i2cChannel: number): Promise { + return await this.embedded.getI2CWriteStatus(i2cChannel); } async setI2CChannelConfiguration( i2cChannel: number, speedCode: I2CSpeedCode, ): Promise { - return this.embedded.setI2CChannelConfiguration(i2cChannel, speedCode); + return await this.embedded.setI2CChannelConfiguration(i2cChannel, speedCode); } - readI2CMultipleBytes( + async readI2CMultipleBytes( i2cChannel: number, slaveAddress: number, numBytesToRead: number, ): Promise { - return this.embedded.readI2CMultipleBytes( + return await this.embedded.readI2CMultipleBytes( i2cChannel, slaveAddress, numBytesToRead, From 420a8deea25983c34e34d46815d692e4b8b4a294 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 16 Aug 2023 09:23:14 -0500 Subject: [PATCH 76/81] update I2C methods --- .../control-hub/src/internal/ControlHub.ts | 26 +++++++++------- .../ControlHubConnectedExpansionHub.ts | 30 +++++++++---------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 5fd289c2..321587a0 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -457,14 +457,6 @@ export class ControlHubInternal implements ControlHub { return await this.embedded.getI2CChannelConfiguration(i2cChannel); } - async getI2CReadStatus(i2cChannel: number): Promise { - return await this.embedded.getI2CReadStatus(i2cChannel); - } - - async getI2CWriteStatus(i2cChannel: number): Promise { - return await this.embedded.getI2CWriteStatus(i2cChannel); - } - async setI2CChannelConfiguration( i2cChannel: number, speedCode: I2CSpeedCode, @@ -472,11 +464,25 @@ export class ControlHubInternal implements ControlHub { return await this.embedded.setI2CChannelConfiguration(i2cChannel, speedCode); } + async readI2CRegister( + i2cChannel: number, + targetAddress: number, + numBytesToRead: number, + register: number, + ): Promise { + return await this.embedded.readI2CRegister( + i2cChannel, + targetAddress, + numBytesToRead, + register + ); + } + async readI2CMultipleBytes( i2cChannel: number, slaveAddress: number, numBytesToRead: number, - ): Promise { + ): Promise { return await this.embedded.readI2CMultipleBytes( i2cChannel, slaveAddress, @@ -484,7 +490,7 @@ export class ControlHubInternal implements ControlHub { ); } - async readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + async readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { return await this.embedded.readI2CSingleByte(i2cChannel, slaveAddress); } diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 0bd99298..10ed827c 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -1,14 +1,11 @@ import { BulkInputData, - ClosedLoopControlAlgorithm, - ControlHub, + ClosedLoopControlAlgorithm, ControlHub, DebugGroup, DigitalChannelDirection, DigitalState, ExpansionHub, - I2CReadStatus, I2CSpeedCode, - I2CWriteStatus, LedPattern, ModuleInterface, ModuleStatus, @@ -21,7 +18,7 @@ import { RevHubType, Rgb, VerbosityLevel, - Version, + Version } from "@rev-robotics/rev-hub-core"; import { EventEmitter } from "events"; @@ -503,29 +500,30 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { : I2CSpeedCode.SpeedCode100_Kbps; } - getI2CReadStatus(i2cChannel: number): Promise { - throw new Error("not implemented"); - } - - getI2CWriteStatus(i2cChannel: number): Promise { + async readI2CRegister( + i2cChannel: number, + targetAddress: number, + numBytesToRead: number, + register: number, + ): Promise { throw new Error("not implemented"); } readI2CMultipleBytes( i2cChannel: number, - slaveAddress: number, + targetAddress: number, numBytesToRead: number, - ): Promise { + ): Promise { throw new Error("not implemented"); } - readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { + readI2CSingleByte(i2cChannel: number, targetAddress: number): Promise { throw new Error("not implemented"); } writeI2CMultipleBytes( i2cChannel: number, - slaveAddress: number, + targetAddress: number, bytes: number[], ): Promise { throw new Error("not implemented"); @@ -533,7 +531,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { writeI2CReadMultipleBytes( i2cChannel: number, - slaveAddress: number, + targetAddress: number, numBytesToRead: number, startAddress: number, ): Promise { @@ -542,7 +540,7 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { writeI2CSingleByte( i2cChannel: number, - slaveAddress: number, + targetAddress: number, byte: number, ): Promise { throw new Error("not implemented"); From 6c09ca6d1fd2d6ab34c7b695383c0bf098cb3847 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 16 Aug 2023 09:24:42 -0500 Subject: [PATCH 77/81] Add method overloads to ControlHub --- packages/core/src/ControlHub.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/core/src/ControlHub.ts b/packages/core/src/ControlHub.ts index 7e835847..06f9f6e8 100644 --- a/packages/core/src/ControlHub.ts +++ b/packages/core/src/ControlHub.ts @@ -1,9 +1,18 @@ -import { ExpansionHub } from "./ExpansionHub.js"; +import { ExpansionHub, ParentExpansionHub } from "./ExpansionHub.js"; import { ParentRevHub } from "./RevHub.js"; +import { ModuleStatus } from "./ModuleStatus.js"; export interface ControlHub extends ExpansionHub, ParentRevHub { + on(eventName: "error", listener: (error: Error) => void): this; + on(eventName: "statusChanged", listener: (status: ModuleStatus) => void): this; + on( + eventName: "addressChanged", + listener: (oldAddress: number, newAddress: number) => void, + ): this; + on(eventName: "sessionEnded", listener: () => void): this; + addUsbConnectedHub( serialNumber: string, moduleAddress: number, - ): Promise; + ): Promise; } From a38111d4ce7d30ae6730a5c55fab465ff46530ff Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 16 Aug 2023 09:54:19 -0500 Subject: [PATCH 78/81] various fixes --- .../control-hub/src/internal/ControlHub.ts | 20 +++++++++---------- .../ControlHubConnectedExpansionHub.ts | 4 ++-- packages/core/src/ExpansionHub.ts | 6 +----- .../src/internal/ExpansionHub.ts | 2 +- packages/sample/src/command/distance.ts | 2 +- packages/sample/src/command/list.ts | 4 ++-- packages/sample/src/command/log.ts | 3 +-- packages/sample/src/command/servo.ts | 2 +- 8 files changed, 19 insertions(+), 24 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 321587a0..0578cc3a 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -480,37 +480,37 @@ export class ControlHubInternal implements ControlHub { async readI2CMultipleBytes( i2cChannel: number, - slaveAddress: number, + targetAddress: number, numBytesToRead: number, ): Promise { return await this.embedded.readI2CMultipleBytes( i2cChannel, - slaveAddress, + targetAddress, numBytesToRead, ); } - async readI2CSingleByte(i2cChannel: number, slaveAddress: number): Promise { - return await this.embedded.readI2CSingleByte(i2cChannel, slaveAddress); + async readI2CSingleByte(i2cChannel: number, targetAddress: number): Promise { + return await this.embedded.readI2CSingleByte(i2cChannel, targetAddress); } async writeI2CMultipleBytes( i2cChannel: number, - slaveAddress: number, + targetAddress: number, bytes: number[], ): Promise { - return await this.embedded.writeI2CMultipleBytes(i2cChannel, slaveAddress, bytes); + return await this.embedded.writeI2CMultipleBytes(i2cChannel, targetAddress, bytes); } async writeI2CReadMultipleBytes( i2cChannel: number, - slaveAddress: number, + targetAddress: number, numBytesToRead: number, startAddress: number, ): Promise { return await this.embedded.writeI2CReadMultipleBytes( i2cChannel, - slaveAddress, + targetAddress, numBytesToRead, startAddress, ); @@ -518,10 +518,10 @@ export class ControlHubInternal implements ControlHub { async writeI2CSingleByte( i2cChannel: number, - slaveAddress: number, + targetAddress: number, byte: number, ): Promise { - return await this.embedded.writeI2CSingleByte(i2cChannel, slaveAddress, byte); + return await this.embedded.writeI2CSingleByte(i2cChannel, targetAddress, byte); } async readVersion(): Promise { diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 10ed827c..769c4ae0 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -603,9 +603,9 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { } async getDigitalDirection(dioPin: number): Promise { - let isOutput = await this.sendCommand("getDigitalDirection", { + let isOutput = await this.sendCommand("isDigitalOutput", { hId: this.id, - channel: dioPin, + c: dioPin, }); return isOutput ? DigitalChannelDirection.Output : DigitalChannelDirection.Input; diff --git a/packages/core/src/ExpansionHub.ts b/packages/core/src/ExpansionHub.ts index 7aa2ac66..4580ddf8 100644 --- a/packages/core/src/ExpansionHub.ts +++ b/packages/core/src/ExpansionHub.ts @@ -9,8 +9,6 @@ import { VerbosityLevel } from "./VerbosityLevel.js"; import { Version } from "./Version.js"; import { DigitalChannelDirection } from "./DigitalChannelDirection.js"; import { I2CSpeedCode } from "./I2CSpeedCode.js"; -import { I2CWriteStatus } from "./I2CWriteStatus.js"; -import { I2CReadStatus } from "./I2CReadStatus.js"; import { MotorMode } from "./MotorMode.js"; import { PidCoefficients } from "./PidCoefficients.js"; import { PidfCoefficients } from "./PidfCoefficients.js"; @@ -30,8 +28,6 @@ export interface ExpansionHub extends RevHub { * it has been closed. */ close(): void; - sendWriteCommand(packetTypeID: number, payload: number[]): Promise; - sendReadCommand(packetTypeID: number, payload: number[]): Promise; getModuleStatus(clearStatusAfterResponse: boolean): Promise; sendKeepAlive(): Promise; sendFailSafe(): Promise; @@ -239,7 +235,7 @@ export interface ExpansionHub extends RevHub { */ readI2CRegister( i2cChannel: number, - slaveAddress: number, + targetAddress: number, numBytesToRead: number, register: number, ): Promise; diff --git a/packages/expansion-hub/src/internal/ExpansionHub.ts b/packages/expansion-hub/src/internal/ExpansionHub.ts index 9feff2d7..297a17b3 100644 --- a/packages/expansion-hub/src/internal/ExpansionHub.ts +++ b/packages/expansion-hub/src/internal/ExpansionHub.ts @@ -6,6 +6,7 @@ import { DigitalChannelDirection, DigitalState, ExpansionHub, GeneralSerialError, + I2cOperationInProgressError, I2CReadStatus, I2CSpeedCode, I2CWriteStatus, @@ -15,7 +16,6 @@ import { MotorMode, NackCode, nackCodeToError, NoExpansionHubWithAddressError, ParameterOutOfRangeError, - I2cOperationInProgressError, ParentRevHub, PidCoefficients, PidfCoefficients, diff --git a/packages/sample/src/command/distance.ts b/packages/sample/src/command/distance.ts index 99615eac..4db57ecb 100644 --- a/packages/sample/src/command/distance.ts +++ b/packages/sample/src/command/distance.ts @@ -1,5 +1,5 @@ -import { ExpansionHub } from "@rev-robotics/rev-hub-core"; import { DistanceSensor } from "@rev-robotics/distance-sensor"; +import { ExpansionHub } from "@rev-robotics/rev-hub-core"; export async function distance( hub: ExpansionHub, diff --git a/packages/sample/src/command/list.ts b/packages/sample/src/command/list.ts index f30887d3..512b6bcf 100644 --- a/packages/sample/src/command/list.ts +++ b/packages/sample/src/command/list.ts @@ -1,7 +1,7 @@ import { openConnectedExpansionHubs } from "@rev-robotics/expansion-hub"; import { controlHubHierarchyToString } from "../HubStringify.js"; -import {ExpansionHub} from "@rev-robotics/rev-hub-core"; -import {openUsbControlHubsAndChildren} from "../open-control-hub.js"; +import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import { openUsbControlHubsAndChildren } from "../open-control-hub.js"; export async function list() { let usbControlHubs = await openUsbControlHubsAndChildren(); diff --git a/packages/sample/src/command/log.ts b/packages/sample/src/command/log.ts index 666f996c..d1053b50 100644 --- a/packages/sample/src/command/log.ts +++ b/packages/sample/src/command/log.ts @@ -1,5 +1,4 @@ -import { DebugGroup, VerbosityLevel } from "@rev-robotics/rhsplib"; -import { ExpansionHub } from "@rev-robotics/rev-hub-core"; +import { ExpansionHub, DebugGroup, VerbosityLevel } from "@rev-robotics/rev-hub-core"; export async function injectLog(hub: ExpansionHub, hint: string) { await hub.injectDataLogHint(hint); diff --git a/packages/sample/src/command/servo.ts b/packages/sample/src/command/servo.ts index 8c90d1be..9b909b3f 100644 --- a/packages/sample/src/command/servo.ts +++ b/packages/sample/src/command/servo.ts @@ -1,4 +1,4 @@ -import {ExpansionHub} from "@rev-robotics/rev-hub-core"; +import { ExpansionHub } from "@rev-robotics/rev-hub-core"; export async function runServo(hub: ExpansionHub, channel: number, pulseWidth: number, framePeriod: number) { await hub.setServoConfiguration(channel, framePeriod); From 230c40d014686f0cff14836915b3b6ad394e42a3 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 16 Aug 2023 09:58:22 -0500 Subject: [PATCH 79/81] implement I2C commands --- .../control-hub/src/internal/ControlHub.ts | 14 ------ .../ControlHubConnectedExpansionHub.ts | 43 +++++++++++-------- 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/packages/control-hub/src/internal/ControlHub.ts b/packages/control-hub/src/internal/ControlHub.ts index 0578cc3a..9f94d446 100644 --- a/packages/control-hub/src/internal/ControlHub.ts +++ b/packages/control-hub/src/internal/ControlHub.ts @@ -502,20 +502,6 @@ export class ControlHubInternal implements ControlHub { return await this.embedded.writeI2CMultipleBytes(i2cChannel, targetAddress, bytes); } - async writeI2CReadMultipleBytes( - i2cChannel: number, - targetAddress: number, - numBytesToRead: number, - startAddress: number, - ): Promise { - return await this.embedded.writeI2CReadMultipleBytes( - i2cChannel, - targetAddress, - numBytesToRead, - startAddress, - ); - } - async writeI2CSingleByte( i2cChannel: number, targetAddress: number, diff --git a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts index 769c4ae0..e815210e 100644 --- a/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts +++ b/packages/control-hub/src/internal/ControlHubConnectedExpansionHub.ts @@ -506,44 +506,51 @@ export class ControlHubConnectedExpansionHub implements ParentExpansionHub { numBytesToRead: number, register: number, ): Promise { - throw new Error("not implemented"); + return await this.sendCommand("readI2cRegister", { + hId: this.id, + a: targetAddress, + c: i2cChannel, + cb: numBytesToRead, + r: register, + }); } - readI2CMultipleBytes( + async readI2CMultipleBytes( i2cChannel: number, targetAddress: number, numBytesToRead: number, ): Promise { - throw new Error("not implemented"); + return await this.sendCommand("readI2cData", { + hId: this.id, + a: targetAddress, + c: i2cChannel, + cb: numBytesToRead, + }); } - readI2CSingleByte(i2cChannel: number, targetAddress: number): Promise { - throw new Error("not implemented"); + async readI2CSingleByte(i2cChannel: number, targetAddress: number): Promise { + return (await this.readI2CMultipleBytes(i2cChannel, targetAddress, 1))[0]; } - writeI2CMultipleBytes( + async writeI2CMultipleBytes( i2cChannel: number, targetAddress: number, bytes: number[], ): Promise { - throw new Error("not implemented"); - } - - writeI2CReadMultipleBytes( - i2cChannel: number, - targetAddress: number, - numBytesToRead: number, - startAddress: number, - ): Promise { - throw new Error("not implemented"); + await this.sendCommand("writeI2cData", { + hId: this.id, + a: targetAddress, + c: i2cChannel, + d: bytes, + }); } - writeI2CSingleByte( + async writeI2CSingleByte( i2cChannel: number, targetAddress: number, byte: number, ): Promise { - throw new Error("not implemented"); + await this.writeI2CMultipleBytes(i2cChannel, targetAddress, [byte]); } async readVersion(): Promise { From 7b5f66fddbd04792d7d8b0f586a69d0eb487949f Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 16 Aug 2023 11:02:36 -0500 Subject: [PATCH 80/81] declare node addon api in project root --- package-lock.json | 13 +++++++++++++ package.json | 3 +++ 2 files changed, 16 insertions(+) diff --git a/package-lock.json b/package-lock.json index 3cc18f78..be44aad7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,9 @@ "workspaces": [ "packages/*" ], + "dependencies": { + "node-addon-api": "^7.0.0" + }, "devDependencies": { "lerna": "^7.0.0", "nx": "^16.2.1", @@ -4187,6 +4190,11 @@ "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, "node_modules/node-fetch": { "version": "2.6.7", "dev": true, @@ -10233,6 +10241,11 @@ "semver": "^7.3.5" } }, + "node-addon-api": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.0.0.tgz", + "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==" + }, "node-fetch": { "version": "2.6.7", "dev": true, diff --git a/package.json b/package.json index 7a83d032..83532300 100644 --- a/package.json +++ b/package.json @@ -8,5 +8,8 @@ "lerna": "^7.0.0", "prettier": "2.8.8", "nx": "^16.2.1" + }, + "dependencies": { + "node-addon-api": "^7.0.0" } } From c2d5718a0b11f04fb43566de735cc49d61019664 Mon Sep 17 00:00:00 2001 From: LandryNorris Date: Wed, 16 Aug 2023 11:15:28 -0500 Subject: [PATCH 81/81] add missing command implementations --- packages/sample/src/command/set-hub-address.ts | 8 ++++++++ packages/sample/src/command/status.ts | 15 +++++++++++++++ packages/sample/src/main.ts | 4 ++-- 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 packages/sample/src/command/set-hub-address.ts create mode 100644 packages/sample/src/command/status.ts diff --git a/packages/sample/src/command/set-hub-address.ts b/packages/sample/src/command/set-hub-address.ts new file mode 100644 index 00000000..dfec0217 --- /dev/null +++ b/packages/sample/src/command/set-hub-address.ts @@ -0,0 +1,8 @@ +import { ControlHub } from "@rev-robotics/rev-hub-core"; + +export async function setHubAddress(hub: ControlHub, address: number) { + hub.on("addressChanged", (oldAddress, newAddress) => { + console.log(`Address changed from ${oldAddress} -> ${newAddress}`); + }); + await hub.setNewModuleAddress(address); +} diff --git a/packages/sample/src/command/status.ts b/packages/sample/src/command/status.ts new file mode 100644 index 00000000..2564427a --- /dev/null +++ b/packages/sample/src/command/status.ts @@ -0,0 +1,15 @@ +import { ControlHub, ModuleStatus } from "@rev-robotics/rev-hub-core"; + +export async function status(hub: ControlHub) { + hub.on("statusChanged", (status: ModuleStatus) => { + console.log(`Status Changed:\n${JSON.stringify(status)}`); + }); + + hub.on("addressChanged", (oldAddress, newAddress) => { + console.log(`Address Changed: ${oldAddress} -> ${newAddress}`); + }); + + hub.on("sessionEnded", () => { + console.log("Session ended"); + }); +} diff --git a/packages/sample/src/main.ts b/packages/sample/src/main.ts index 736fd0de..a65774b1 100644 --- a/packages/sample/src/main.ts +++ b/packages/sample/src/main.ts @@ -51,8 +51,8 @@ import { distance } from "./command/distance.js"; import { sendFailSafe } from "./command/failsafe.js"; import { queryInterface } from "./command/query.js"; import { openUsbControlHubsAndChildren } from "./open-control-hub.js"; -import { status } from "../dist/command/status.js"; -import { setHubAddress } from "../dist/command/set-hub-address.js"; +import { status } from "./command/status.js"; +import { setHubAddress } from "./command/set-hub-address.js"; function runOnSigint(block: () => void) { process.on("SIGINT", () => {