openvibers/openvibe.bot Commits
Bot: a Network-paired Node's status is accepted (drivers as objects keep their names) (#100)
Changes
@@@ -224,14 +224,18 @@ function createRealtime({ config, keys, userAuth, log = console, now = () => Dat* `status` of a Network-paired device: device_kind, drivers, capabilities and agent_version are persisted* when they differ from the row. Any invalid one → bot.bad_frame and the row unchanged.*/-- async function persistDeclared(conn, msg) {++ async function persistDeclared(conn, frame) {const d = conn.device;++ // OpenVibe.Node's status lists its drivers as objects ({ name, driver, state, … }, internal/protocol Status)++ // where its pairing request lists their names: the row keeps the names either way.++ const driverName = (x) => (typeof x === 'string' ? x : (x && typeof x === 'object' && typeof (x.driver || x.name) === 'string' ? x.driver || x.name : null));++ const msg = Array.isArray(frame.drivers) ? { ...frame, drivers: frame.drivers.map(driverName) } : frame;const has = (k) => msg[k] !== undefined;if ((has('device_kind') && !DEVICE_KINDS.has(msg.device_kind))|| (has('drivers') && !(Array.isArray(msg.drivers) && msg.drivers.every((x) => typeof x === 'string')))|| (has('capabilities') && !(msg.capabilities && typeof msg.capabilities === 'object' && !Array.isArray(msg.capabilities)))|| (has('agent_version') && !(typeof msg.agent_version === 'string' && msg.agent_version.length <= MAX_AGENT_VERSION))) {-- return sendError(conn, 'bot.bad_frame', `device_kind must be one of ${[...DEVICE_KINDS].join('|')}, drivers an array of strings, capabilities an object, agent_version a string of at most ${MAX_AGENT_VERSION}`);++ return sendError(conn, 'bot.bad_frame', `device_kind must be one of ${[...DEVICE_KINDS].join('|')}, drivers an array of names or { name } objects, capabilities an object, agent_version a string of at most ${MAX_AGENT_VERSION}`);}const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);const change = {};@@@ -102,7 +102,7 @@ const WHIP_BASE = 'https://whip.test/ingest';assert.deepStrictEqual(d.drivers, ['pca9685', 'picamera2']);assert.deepStrictEqual(d.capabilities, { camera: true });assert.strictEqual(d.agent_version, '0.3.1');-- for (const bad of [{ device_kind: 'toaster' }, { drivers: 'pca9685' }, { drivers: [1] }, { agent_version: 'x'.repeat(41) }, { capabilities: [] }]) {++ for (const bad of [{ device_kind: 'toaster' }, { drivers: 'pca9685' }, { drivers: [1] }, { drivers: [{ state: 'up' }] }, { agent_version: 'x'.repeat(41) }, { capabilities: [] }]) {const before = c.messages.filter((m) => m.type === 'error').length;c.send({ v: 1, seq: 2, ts: Date.now(), type: 'status', ...bad });await c.waitFor(() => c.messages.filter((m) => m.type === 'error').length > before);@@@ -113,6 +113,13 @@ const WHIP_BASE = 'https://whip.test/ingest';assert.strictEqual(after.kind, 'bridge');assert.deepStrictEqual(after.drivers, ['pca9685', 'picamera2']);assert.strictEqual(after.agent_version, '0.3.1');++ // The Node's own status frame lists drivers as objects (OpenVibe.Node internal/protocol Status): the names stay.++ const errors = c.messages.filter((m) => m.type === 'error').length;++ c.send({ v: 1, seq: 3, ts: Date.now(), type: 'status', firmware: 'x', device_kind: 'bridge', drivers: [{ name: 'adeept', driver: 'adeept_adr036', state: 'up' }, { name: 'dryrun', state: 'down' }], faults: [] });++ let named;++ for (let i = 0; i < 40; i++) { named = await deviceRow(hello.device_id); if (named.drivers.length && named.drivers[0] === 'adeept_adr036') break; await t.wait(25); }++ assert.deepStrictEqual(named.drivers, ['adeept_adr036', 'dryrun']);++ assert.strictEqual(c.messages.filter((m) => m.type === 'error').length, errors, 'no bad_frame for the Node\'s own status');c.close();});
@@ -224,14 +224,18 @@ function createRealtime({ config, keys, userAuth, log = console, now = () => Dat
@@ -224,14 +224,18 @@ function createRealtime({ config, keys, userAuth, log = console, now = () => Dat
* `status` of a Network-paired device: device_kind, drivers, capabilities and agent_version are persisted
* `status` of a Network-paired device: device_kind, drivers, capabilities and agent_version are persisted
* when they differ from the row. Any invalid one → bot.bad_frame and the row unchanged.
* when they differ from the row. Any invalid one → bot.bad_frame and the row unchanged.
*/
*/
- async function persistDeclared(conn, msg) {
+ async function persistDeclared(conn, frame) {
const d = conn.device;
const d = conn.device;
+ // OpenVibe.Node's status lists its drivers as objects ({ name, driver, state, … }, internal/protocol Status)
+ // where its pairing request lists their names: the row keeps the names either way.
+ const driverName = (x) => (typeof x === 'string' ? x : (x && typeof x === 'object' && typeof (x.driver || x.name) === 'string' ? x.driver || x.name : null));
+ const msg = Array.isArray(frame.drivers) ? { ...frame, drivers: frame.drivers.map(driverName) } : frame;
const has = (k) => msg[k] !== undefined;
const has = (k) => msg[k] !== undefined;
if ((has('device_kind') && !DEVICE_KINDS.has(msg.device_kind))
if ((has('device_kind') && !DEVICE_KINDS.has(msg.device_kind))
|| (has('drivers') && !(Array.isArray(msg.drivers) && msg.drivers.every((x) => typeof x === 'string')))
|| (has('drivers') && !(Array.isArray(msg.drivers) && msg.drivers.every((x) => typeof x === 'string')))
|| (has('capabilities') && !(msg.capabilities && typeof msg.capabilities === 'object' && !Array.isArray(msg.capabilities)))
|| (has('capabilities') && !(msg.capabilities && typeof msg.capabilities === 'object' && !Array.isArray(msg.capabilities)))
|| (has('agent_version') && !(typeof msg.agent_version === 'string' && msg.agent_version.length <= MAX_AGENT_VERSION))) {
|| (has('agent_version') && !(typeof msg.agent_version === 'string' && msg.agent_version.length <= MAX_AGENT_VERSION))) {
- return sendError(conn, 'bot.bad_frame', `device_kind must be one of ${[...DEVICE_KINDS].join('|')}, drivers an array of strings, capabilities an object, agent_version a string of at most ${MAX_AGENT_VERSION}`);
+ return sendError(conn, 'bot.bad_frame', `device_kind must be one of ${[...DEVICE_KINDS].join('|')}, drivers an array of names or { name } objects, capabilities an object, agent_version a string of at most ${MAX_AGENT_VERSION}`);
}
}
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
const change = {};
const change = {};
@@ -102,7 +102,7 @@ const WHIP_BASE = 'https://whip.test/ingest';
@@ -102,7 +102,7 @@ const WHIP_BASE = 'https://whip.test/ingest';
assert.deepStrictEqual(d.drivers, ['pca9685', 'picamera2']);
assert.deepStrictEqual(d.drivers, ['pca9685', 'picamera2']);
assert.deepStrictEqual(d.capabilities, { camera: true });
assert.deepStrictEqual(d.capabilities, { camera: true });
assert.strictEqual(d.agent_version, '0.3.1');
assert.strictEqual(d.agent_version, '0.3.1');
- for (const bad of [{ device_kind: 'toaster' }, { drivers: 'pca9685' }, { drivers: [1] }, { agent_version: 'x'.repeat(41) }, { capabilities: [] }]) {
+ for (const bad of [{ device_kind: 'toaster' }, { drivers: 'pca9685' }, { drivers: [1] }, { drivers: [{ state: 'up' }] }, { agent_version: 'x'.repeat(41) }, { capabilities: [] }]) {
const before = c.messages.filter((m) => m.type === 'error').length;
const before = c.messages.filter((m) => m.type === 'error').length;
c.send({ v: 1, seq: 2, ts: Date.now(), type: 'status', ...bad });
c.send({ v: 1, seq: 2, ts: Date.now(), type: 'status', ...bad });
await c.waitFor(() => c.messages.filter((m) => m.type === 'error').length > before);
await c.waitFor(() => c.messages.filter((m) => m.type === 'error').length > before);
@@ -113,6 +113,13 @@ const WHIP_BASE = 'https://whip.test/ingest';
@@ -113,6 +113,13 @@ const WHIP_BASE = 'https://whip.test/ingest';
assert.strictEqual(after.kind, 'bridge');
assert.strictEqual(after.kind, 'bridge');
assert.deepStrictEqual(after.drivers, ['pca9685', 'picamera2']);
assert.deepStrictEqual(after.drivers, ['pca9685', 'picamera2']);
assert.strictEqual(after.agent_version, '0.3.1');
assert.strictEqual(after.agent_version, '0.3.1');
+ // The Node's own status frame lists drivers as objects (OpenVibe.Node internal/protocol Status): the names stay.
+ const errors = c.messages.filter((m) => m.type === 'error').length;
+ c.send({ v: 1, seq: 3, ts: Date.now(), type: 'status', firmware: 'x', device_kind: 'bridge', drivers: [{ name: 'adeept', driver: 'adeept_adr036', state: 'up' }, { name: 'dryrun', state: 'down' }], faults: [] });
+ let named;
+ for (let i = 0; i < 40; i++) { named = await deviceRow(hello.device_id); if (named.drivers.length && named.drivers[0] === 'adeept_adr036') break; await t.wait(25); }
+ assert.deepStrictEqual(named.drivers, ['adeept_adr036', 'dryrun']);
+ assert.strictEqual(c.messages.filter((m) => m.type === 'error').length, errors, 'no bad_frame for the Node\'s own status');
c.close();
c.close();
});
});