openvibers/openvibe.bot Commits
Bot: the front page lists every robot Bot has a profile for (ROS 2, LOOI and a phone joined) (#110)
Changes
@@@ -70,9 +70,14 @@ function sections({ signedIn }) {],}) + showcase.features({title: 'Robots it drives today',++ // One card per robot profile Bot ships (server/profiles): what each one drives, said as its profile says it.++ lede: 'Each has a profile the panel draws its controls from. ONVIF PTZ cameras and a generic relay, for anything a local script can switch, come with them.',items: [{ icon: 'ov:check', title: 'Adeept 4WD Smart Car', text: 'The Raspberry Pi kit, with its parts list and build guide; a mecanum-wheel build has its own profile. The first robot on OpenVibe.Bot.' },-- { icon: 'ov:check', title: 'Cozmo', text: 'Through the device agent on a computer next to it.' },++ { icon: 'ov:check', title: 'ROS 2 robots', text: 'A TurtleBot 3 or 4, a Jackal or a home-built base on cmd_vel, mecanum and omni bases too: drive, camera, the distance ahead and the battery, through the OpenVibe Node.' },++ { icon: 'ov:check', title: 'LOOI', text: 'The tracked desk robot with a phone for a face: drive and head tilt over Bluetooth from a computer running the OpenVibe Node and the community LOOI driver.' },++ { icon: 'ov:check', title: 'Cozmo', text: 'Drive, head and lift, speech, its face display, lights and camera, through a computer next to it that joins the robot\'s Wi-Fi.' },++ { icon: 'ov:check', title: 'A phone', text: 'Any phone as a robot\'s eyes, voice and face, from its browser with nothing to install: camera, speech, a full-screen face and its torch.' },{ icon: 'ov:check', title: 'A simulated rover', text: 'A rover in a small arena with a camera, a range finder, line sensors, headlights and a horn. Drive it at /try in your browser, with no account and no hardware.' },],}) + `<section class="sc-sec" id="build"><h2>Build for OpenVibe.Bot</h2>@@@ -26,6 +26,10 @@ const { boot, check, done } = require('./helpers/app');assert.match(html, /<link rel="canonical" href="http:\/\/bot\.test\/">/);assert.match(html, /href="\/auth\/login\?next=%2Frobots">Sign in with OpenVibe/);assert.strictEqual((html.match(/<h1[ >]/g) || []).length, 1, 'one h1');++ // Every robot Bot ships a profile for is on the front page: six cards under "Robots it drives today".++ const robots = (/<section class="sc-sec"[^>]*aria-labelledby="sc-robots-it-drives-today"[\s\S]*?<\/section>/.exec(html) || [''])[0];++ assert.deepStrictEqual([...robots.matchAll(/<b>([^<]+)<\/b>/g)].map((m) => m[1]), ['Adeept 4WD Smart Car', 'ROS 2 robots', 'LOOI', 'Cozmo', 'A phone', 'A simulated rover']);++ for (const id of ['adeept.adr036', 'ros2.diffdrive', 'looi', 'cozmo', 'phone.camera', 'sim.rover']) assert.ok(require('fs').existsSync(require('path').join(__dirname, '..', 'server', 'profiles', `${id}.json`)), `${id} is a shipped profile`);const css = html.match(/href="(\/shared\/showcase\.css\?v=[0-9a-f]{12})"/);assert.ok(css, 'links the showcase stylesheet');const sheet = await get(css[1]);@@@ -37,7 +41,8 @@ const { boot, check, done } = require('./helpers/app');await check('GET /: no promise the service cannot keep (video waits for OpenRestream; no store, no unsupported boards)', async () => {const html = await (await get('/')).text();assert.match(html, /sends its camera over WebRTC to OpenRestream and the panel plays it live/);-- for (const claim of [/ESP32/, /ROS 2/, /Android/, /arrive paired/i, /\bbuy\b/i, /webhook/i]) assert.ok(!claim.test(html), `no ${claim}`);++ // ROS 2 left this list with Bot#95 (ros2.diffdrive, ros2.holonomic, the Node's plugins/ros2 driver).++ for (const claim of [/ESP32/, /Android/, /arrive paired/i, /\bbuy\b/i, /webhook/i]) assert.ok(!claim.test(html), `no ${claim}`);});await check('GET /: signed in, the first action opens your robots', async () => {
@@ -70,9 +70,14 @@ function sections({ signedIn }) {
@@ -70,9 +70,14 @@ function sections({ signedIn }) {
],
],
}) + showcase.features({
}) + showcase.features({
title: 'Robots it drives today',
title: 'Robots it drives today',
+ // One card per robot profile Bot ships (server/profiles): what each one drives, said as its profile says it.
+ lede: 'Each has a profile the panel draws its controls from. ONVIF PTZ cameras and a generic relay, for anything a local script can switch, come with them.',
items: [
items: [
{ icon: 'ov:check', title: 'Adeept 4WD Smart Car', text: 'The Raspberry Pi kit, with its parts list and build guide; a mecanum-wheel build has its own profile. The first robot on OpenVibe.Bot.' },
{ icon: 'ov:check', title: 'Adeept 4WD Smart Car', text: 'The Raspberry Pi kit, with its parts list and build guide; a mecanum-wheel build has its own profile. The first robot on OpenVibe.Bot.' },
- { icon: 'ov:check', title: 'Cozmo', text: 'Through the device agent on a computer next to it.' },
+ { icon: 'ov:check', title: 'ROS 2 robots', text: 'A TurtleBot 3 or 4, a Jackal or a home-built base on cmd_vel, mecanum and omni bases too: drive, camera, the distance ahead and the battery, through the OpenVibe Node.' },
+ { icon: 'ov:check', title: 'LOOI', text: 'The tracked desk robot with a phone for a face: drive and head tilt over Bluetooth from a computer running the OpenVibe Node and the community LOOI driver.' },
+ { icon: 'ov:check', title: 'Cozmo', text: 'Drive, head and lift, speech, its face display, lights and camera, through a computer next to it that joins the robot\'s Wi-Fi.' },
+ { icon: 'ov:check', title: 'A phone', text: 'Any phone as a robot\'s eyes, voice and face, from its browser with nothing to install: camera, speech, a full-screen face and its torch.' },
{ icon: 'ov:check', title: 'A simulated rover', text: 'A rover in a small arena with a camera, a range finder, line sensors, headlights and a horn. Drive it at /try in your browser, with no account and no hardware.' },
{ icon: 'ov:check', title: 'A simulated rover', text: 'A rover in a small arena with a camera, a range finder, line sensors, headlights and a horn. Drive it at /try in your browser, with no account and no hardware.' },
],
],
}) + `<section class="sc-sec" id="build"><h2>Build for OpenVibe.Bot</h2>
}) + `<section class="sc-sec" id="build"><h2>Build for OpenVibe.Bot</h2>
@@ -26,6 +26,10 @@ const { boot, check, done } = require('./helpers/app');
@@ -26,6 +26,10 @@ const { boot, check, done } = require('./helpers/app');
assert.match(html, /<link rel="canonical" href="http:\/\/bot\.test\/">/);
assert.match(html, /<link rel="canonical" href="http:\/\/bot\.test\/">/);
assert.match(html, /href="\/auth\/login\?next=%2Frobots">Sign in with OpenVibe/);
assert.match(html, /href="\/auth\/login\?next=%2Frobots">Sign in with OpenVibe/);
assert.strictEqual((html.match(/<h1[ >]/g) || []).length, 1, 'one h1');
assert.strictEqual((html.match(/<h1[ >]/g) || []).length, 1, 'one h1');
+ // Every robot Bot ships a profile for is on the front page: six cards under "Robots it drives today".
+ const robots = (/<section class="sc-sec"[^>]*aria-labelledby="sc-robots-it-drives-today"[\s\S]*?<\/section>/.exec(html) || [''])[0];
+ assert.deepStrictEqual([...robots.matchAll(/<b>([^<]+)<\/b>/g)].map((m) => m[1]), ['Adeept 4WD Smart Car', 'ROS 2 robots', 'LOOI', 'Cozmo', 'A phone', 'A simulated rover']);
+ for (const id of ['adeept.adr036', 'ros2.diffdrive', 'looi', 'cozmo', 'phone.camera', 'sim.rover']) assert.ok(require('fs').existsSync(require('path').join(__dirname, '..', 'server', 'profiles', `${id}.json`)), `${id} is a shipped profile`);
const css = html.match(/href="(\/shared\/showcase\.css\?v=[0-9a-f]{12})"/);
const css = html.match(/href="(\/shared\/showcase\.css\?v=[0-9a-f]{12})"/);
assert.ok(css, 'links the showcase stylesheet');
assert.ok(css, 'links the showcase stylesheet');
const sheet = await get(css[1]);
const sheet = await get(css[1]);
@@ -37,7 +41,8 @@ const { boot, check, done } = require('./helpers/app');
@@ -37,7 +41,8 @@ const { boot, check, done } = require('./helpers/app');
await check('GET /: no promise the service cannot keep (video waits for OpenRestream; no store, no unsupported boards)', async () => {
await check('GET /: no promise the service cannot keep (video waits for OpenRestream; no store, no unsupported boards)', async () => {
const html = await (await get('/')).text();
const html = await (await get('/')).text();
assert.match(html, /sends its camera over WebRTC to OpenRestream and the panel plays it live/);
assert.match(html, /sends its camera over WebRTC to OpenRestream and the panel plays it live/);
- for (const claim of [/ESP32/, /ROS 2/, /Android/, /arrive paired/i, /\bbuy\b/i, /webhook/i]) assert.ok(!claim.test(html), `no ${claim}`);
+ // ROS 2 left this list with Bot#95 (ros2.diffdrive, ros2.holonomic, the Node's plugins/ros2 driver).
+ for (const claim of [/ESP32/, /Android/, /arrive paired/i, /\bbuy\b/i, /webhook/i]) assert.ok(!claim.test(html), `no ${claim}`);
});
});
await check('GET /: signed in, the first action opens your robots', async () => {
await check('GET /: signed in, the first action opens your robots', async () => {