Compare commits
1 Commits
master
...
No-Web-Com
| Author | SHA1 | Date | |
|---|---|---|---|
|
c32c27b3cb
|
18
launch-bypass.sh
Executable file
18
launch-bypass.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# RoboCommander - Jibo Robot Direct Connection Launcher
|
||||||
|
# Bypasses portal.jibo.com and connects directly to robot
|
||||||
|
|
||||||
|
export JIBO_BYPASS_PORTAL=1
|
||||||
|
export JIBO_OFFLINE_IP="192.168.1.15"
|
||||||
|
export JIBO_OFFLINE_SERIALS="coral-watt-serrano-woven"
|
||||||
|
export JIBO_OFFLINE_SKIP_TLS=1
|
||||||
|
# Use self-signed client certificate for TLS client auth
|
||||||
|
export JIBO_OFFLINE_CERT_PATH="/home/kevin/jiboauth/jibo-client.crt"
|
||||||
|
export JIBO_OFFLINE_KEY_PATH="/home/kevin/jiboauth/jibo-client.key"
|
||||||
|
|
||||||
|
# Launch the Electron app
|
||||||
|
cd ~/Documents/RoboCommander
|
||||||
|
./node_modules/electron/dist/electron .
|
||||||
|
|
||||||
|
|
||||||
39
node_modules/@jibo/apptoolkit-library/lib/Account.js
generated
vendored
39
node_modules/@jibo/apptoolkit-library/lib/Account.js
generated
vendored
@@ -3,6 +3,26 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
const axios_1 = require("axios");
|
const axios_1 = require("axios");
|
||||||
const constants_1 = require("./constants");
|
const constants_1 = require("./constants");
|
||||||
const Robot_1 = require("./Robot");
|
const Robot_1 = require("./Robot");
|
||||||
|
function isBypassEnabled() {
|
||||||
|
const raw = process.env.JIBO_BYPASS_PORTAL || "";
|
||||||
|
return raw === "1" || raw.toLowerCase() === "true";
|
||||||
|
}
|
||||||
|
function getOfflineSerials() {
|
||||||
|
const raw = process.env.JIBO_OFFLINE_SERIALS || process.env.JIBO_OFFLINE_SERIAL || "";
|
||||||
|
const serials = raw.split(",").map(s => s.trim()).filter(Boolean);
|
||||||
|
return serials.length ? serials : ["offline-jibo"];
|
||||||
|
}
|
||||||
|
function buildOfflineConnectionConfig() {
|
||||||
|
return {
|
||||||
|
ip: process.env.JIBO_OFFLINE_IP,
|
||||||
|
certPath: process.env.JIBO_OFFLINE_CERT_PATH,
|
||||||
|
certPem: process.env.JIBO_OFFLINE_CERT_PEM,
|
||||||
|
keyPath: process.env.JIBO_OFFLINE_KEY_PATH,
|
||||||
|
keyPem: process.env.JIBO_OFFLINE_KEY_PEM,
|
||||||
|
fingerprint: process.env.JIBO_OFFLINE_FINGERPRINT,
|
||||||
|
skipTls: process.env.JIBO_OFFLINE_SKIP_TLS === '1' || process.env.JIBO_OFFLINE_SKIP_TLS === 'true',
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @description A reference to a Jibo account. Log in here to get an API handle
|
* @description A reference to a Jibo account. Log in here to get an API handle
|
||||||
* to a Jibo robot or robots.
|
* to a Jibo robot or robots.
|
||||||
@@ -21,6 +41,12 @@ class Account {
|
|||||||
* @method Account#login
|
* @method Account#login
|
||||||
*/
|
*/
|
||||||
async login() {
|
async login() {
|
||||||
|
if (isBypassEnabled()) {
|
||||||
|
console.log("[JIBO_BYPASS] login(): bypassing portal.jibo.com token request");
|
||||||
|
this._accessToken = process.env.JIBO_OFFLINE_ACCESS_TOKEN || "offline-token";
|
||||||
|
this._tokenType = process.env.JIBO_OFFLINE_TOKEN_TYPE || "Bearer";
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this._accessToken) {
|
if (this._accessToken) {
|
||||||
this.logout();
|
this.logout();
|
||||||
}
|
}
|
||||||
@@ -43,6 +69,19 @@ class Account {
|
|||||||
* @returns {Promise<Robot[]>}
|
* @returns {Promise<Robot[]>}
|
||||||
*/
|
*/
|
||||||
async getRobots() {
|
async getRobots() {
|
||||||
|
if (isBypassEnabled()) {
|
||||||
|
console.log("[JIBO_BYPASS] getRobots(): returning offline robot handles");
|
||||||
|
const tokenType = this._tokenType || process.env.JIBO_OFFLINE_TOKEN_TYPE || "Bearer";
|
||||||
|
const accessToken = this._accessToken || process.env.JIBO_OFFLINE_ACCESS_TOKEN || "offline-token";
|
||||||
|
const config = buildOfflineConnectionConfig();
|
||||||
|
return getOfflineSerials().map(serial => {
|
||||||
|
const robot = new Robot_1.Robot(serial, tokenType, accessToken);
|
||||||
|
if (typeof robot.configureDirectConnection === "function") {
|
||||||
|
robot.configureDirectConnection(config);
|
||||||
|
}
|
||||||
|
return robot;
|
||||||
|
});
|
||||||
|
}
|
||||||
if (!this._accessToken) {
|
if (!this._accessToken) {
|
||||||
throw new Error('Not logged in');
|
throw new Error('Not logged in');
|
||||||
}
|
}
|
||||||
|
|||||||
79
node_modules/@jibo/apptoolkit-library/lib/Robot.js
generated
vendored
79
node_modules/@jibo/apptoolkit-library/lib/Robot.js
generated
vendored
@@ -4,6 +4,18 @@ const axios_1 = require("axios");
|
|||||||
const events_1 = require("events");
|
const events_1 = require("events");
|
||||||
const command_requester_1 = require("@jibo/command-requester");
|
const command_requester_1 = require("@jibo/command-requester");
|
||||||
const constants_1 = require("./constants");
|
const constants_1 = require("./constants");
|
||||||
|
const fs_1 = require("fs");
|
||||||
|
function readIfExists(path) {
|
||||||
|
if (!path) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return fs_1.readFileSync(path, "utf8");
|
||||||
|
}
|
||||||
|
catch (_a) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* An API handle to a Jibo robot, used to request commands
|
* An API handle to a Jibo robot, used to request commands
|
||||||
* @class Robot
|
* @class Robot
|
||||||
@@ -38,6 +50,34 @@ class Robot extends events_1.EventEmitter {
|
|||||||
get requester() {
|
get requester() {
|
||||||
return this._requester;
|
return this._requester;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Configure direct/offline connection values to avoid cloud lookup.
|
||||||
|
* Accepts inline PEM values or *_PATH values.
|
||||||
|
*/
|
||||||
|
configureDirectConnection(config) {
|
||||||
|
if (!config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("[JIBO_BYPASS] configureDirectConnection(): applying offline connection config");
|
||||||
|
if (config.ip) {
|
||||||
|
this._ip = config.ip;
|
||||||
|
}
|
||||||
|
if (config.skipTls) {
|
||||||
|
this._skipTls = true;
|
||||||
|
console.log("[JIBO_BYPASS] configureDirectConnection(): TLS disabled for direct websocket connection");
|
||||||
|
}
|
||||||
|
if (config.fingerprint) {
|
||||||
|
this._fingerprint = config.fingerprint;
|
||||||
|
}
|
||||||
|
const cert = config.certPem || readIfExists(config.certPath);
|
||||||
|
if (cert) {
|
||||||
|
this._certificate = cert;
|
||||||
|
}
|
||||||
|
const key = config.keyPem || readIfExists(config.keyPath);
|
||||||
|
if (key) {
|
||||||
|
this._key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Establish a connection to this robot
|
* Establish a connection to this robot
|
||||||
* @method Robot.connect
|
* @method Robot.connect
|
||||||
@@ -50,24 +90,35 @@ class Robot extends events_1.EventEmitter {
|
|||||||
await this._requestCertificate();
|
await this._requestCertificate();
|
||||||
await this._retrieveCertificate();
|
await this._retrieveCertificate();
|
||||||
}
|
}
|
||||||
|
if (!this._skipTls && (!this._certificate || !this._key)) {
|
||||||
|
console.log("[JIBO_BYPASS] connect(): missing direct credentials", {
|
||||||
|
hasIp: !!this._ip,
|
||||||
|
hasCert: !!this._certificate,
|
||||||
|
hasKey: !!this._key,
|
||||||
|
hasFingerprint: !!this._fingerprint,
|
||||||
|
});
|
||||||
|
throw new Error("Missing certificate/key for direct robot connection");
|
||||||
|
}
|
||||||
const options = {
|
const options = {
|
||||||
port: constants_1.PORT,
|
port: constants_1.PORT,
|
||||||
key: this._key,
|
|
||||||
cert: this._certificate,
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
perMessageDeflate: false,
|
perMessageDeflate: false,
|
||||||
fingerprint: this._fingerprint,
|
|
||||||
};
|
};
|
||||||
|
if (!this._skipTls) {
|
||||||
|
options.key = this._key;
|
||||||
|
options.cert = this._certificate;
|
||||||
|
options.rejectUnauthorized = false;
|
||||||
|
options.fingerprint = this._fingerprint;
|
||||||
|
}
|
||||||
this._requester = new command_requester_1.CommandRequester();
|
this._requester = new command_requester_1.CommandRequester();
|
||||||
this._requester.disconnected.on(data => {
|
this._requester.disconnected.on(data => {
|
||||||
this._connected = false;
|
this._connected = false;
|
||||||
this.emit('disconnected', data);
|
this.emit("disconnected", data);
|
||||||
this.emit('status', 'disconnected');
|
this.emit("status", "disconnected");
|
||||||
});
|
});
|
||||||
return this._requester.connect(this._ip, options)
|
return this._requester.connect(this._ip, options)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this._connected = true;
|
this._connected = true;
|
||||||
this.emit('status', 'connected');
|
this.emit("status", "connected");
|
||||||
})
|
})
|
||||||
.catch(err => { throw new Error(err.message); });
|
.catch(err => { throw new Error(err.message); });
|
||||||
}
|
}
|
||||||
@@ -79,27 +130,29 @@ class Robot extends events_1.EventEmitter {
|
|||||||
// Don't throw an error if this is called in a late cleanup and this
|
// Don't throw an error if this is called in a late cleanup and this
|
||||||
// falls out of scope
|
// falls out of scope
|
||||||
if (this) {
|
if (this) {
|
||||||
|
if (this._requester) {
|
||||||
this._requester.disconnect();
|
this._requester.disconnect();
|
||||||
|
}
|
||||||
this._certificate = null;
|
this._certificate = null;
|
||||||
this._connected = false;
|
this._connected = false;
|
||||||
this._fingerprint = null;
|
this._fingerprint = null;
|
||||||
this._ip = null;
|
this._ip = null;
|
||||||
this._key = null;
|
this._key = null;
|
||||||
this._requester = null;
|
this._requester = null;
|
||||||
this.emit('status', 'disconnected');
|
this.emit("status", "disconnected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async _requestCertificate() {
|
async _requestCertificate() {
|
||||||
const certificateCreationUri = `https://${constants_1.ENDPOINT}/rom/v1/certificates`;
|
const certificateCreationUri = `https://${constants_1.ENDPOINT}/rom/v1/certificates`;
|
||||||
const body = { friendlyId: this.serialName };
|
const body = { friendlyId: this.serialName };
|
||||||
const headers = { 'Authorization': `${this.tokenType} ${this.accessToken}` };
|
const headers = { Authorization: `${this.tokenType} ${this.accessToken}` };
|
||||||
await axios_1.default.post(certificateCreationUri, body, { headers })
|
await axios_1.default.post(certificateCreationUri, body, { headers })
|
||||||
.then(() => this.emit('status', 'certificateRequested'))
|
.then(() => this.emit("status", "certificateRequested"))
|
||||||
.catch(err => { throw new Error(err.message); });
|
.catch(err => { throw new Error(err.message); });
|
||||||
}
|
}
|
||||||
async _retrieveCertificate() {
|
async _retrieveCertificate() {
|
||||||
const certificateRetrievalUri = `https://${constants_1.ENDPOINT}/rom/v1/certificates/client?friendlyId=${this.serialName}`;
|
const certificateRetrievalUri = `https://${constants_1.ENDPOINT}/rom/v1/certificates/client?friendlyId=${this.serialName}`;
|
||||||
const headers = { 'Authorization': `${this.tokenType} ${this.accessToken}` };
|
const headers = { Authorization: `${this.tokenType} ${this.accessToken}` };
|
||||||
this._ip = null;
|
this._ip = null;
|
||||||
let numTries = 0;
|
let numTries = 0;
|
||||||
while (!this._ip && numTries < constants_1.MAX_CERT_TRIES) {
|
while (!this._ip && numTries < constants_1.MAX_CERT_TRIES) {
|
||||||
@@ -119,9 +172,9 @@ class Robot extends events_1.EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this._ip) {
|
if (!this._ip) {
|
||||||
throw new Error('Failed to retrieve certificate');
|
throw new Error("Failed to retrieve certificate");
|
||||||
}
|
}
|
||||||
this.emit('status', 'certificateReceived');
|
this.emit("status", "certificateReceived");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.Robot = Robot;
|
exports.Robot = Robot;
|
||||||
|
|||||||
2
node_modules/@jibo/apptoolkit-library/lib/constants.js
generated
vendored
2
node_modules/@jibo/apptoolkit-library/lib/constants.js
generated
vendored
@@ -2,5 +2,5 @@
|
|||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.ENDPOINT = 'portal.jibo.com';
|
exports.ENDPOINT = 'portal.jibo.com';
|
||||||
exports.MAX_CERT_TRIES = 40;
|
exports.MAX_CERT_TRIES = 40;
|
||||||
exports.PORT = 7160;
|
exports.PORT = 8160;
|
||||||
//# sourceMappingURL=constants.js.map
|
//# sourceMappingURL=constants.js.map
|
||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user