From 5c706a13b42a241340f5cd3094bb309f21b23991 Mon Sep 17 00:00:00 2001 From: Kevin Date: Wed, 18 Mar 2026 23:31:33 +0200 Subject: [PATCH] HEY JIBO! --- .../lib/jibo-embodied-dialog.js | 85 ++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/V3.1/build/opt/jibo/Jibo/Skills/@be/be/node_modules/jibo-embodied-dialog/lib/jibo-embodied-dialog.js b/V3.1/build/opt/jibo/Jibo/Skills/@be/be/node_modules/jibo-embodied-dialog/lib/jibo-embodied-dialog.js index 4e3073ae..d0129aca 100644 --- a/V3.1/build/opt/jibo/Jibo/Skills/@be/be/node_modules/jibo-embodied-dialog/lib/jibo-embodied-dialog.js +++ b/V3.1/build/opt/jibo/Jibo/Skills/@be/be/node_modules/jibo-embodied-dialog/lib/jibo-embodied-dialog.js @@ -371,6 +371,7 @@ try { catch (e) { } const WIN = 'Jibo Embodied Dialog'; +let hjModeToken = null; class TunableDebug { static setup(embodied) { if (tunable) { @@ -392,6 +393,49 @@ class TunableDebug { Tunable.getButtonField('Disable once', WIN).events.change.on(() => { embodied.listen.disableOnce(); }); + + Tunable.getButtonField('Reset hotword mode', WIN).events.change.on(() => { + try { + const jibo = embodied && embodied.listen && embodied.listen._jibo; + if (jibo && jibo.jetstream && typeof jibo.jetstream.resetHotwordMode === 'function') { + jibo.jetstream.resetHotwordMode().catch(() => { }); + } + } + catch (e) { + // ignore + } + }); + + Tunable.getButtonField('Enable HJ only', WIN).events.change.on(() => { + try { + const jibo = embodied && embodied.listen && embodied.listen._jibo; + const mode = jibo && jibo.jetstream && jibo.jetstream.types && jibo.jetstream.types.HotwordListenMode; + if (!jibo || !jibo.jetstream || !mode || typeof jibo.jetstream.setHotwordMode !== 'function') { + return; + } + if (hjModeToken && typeof hjModeToken.release === 'function') { + hjModeToken.release().catch(() => { }); + hjModeToken = null; + } + hjModeToken = jibo.jetstream.setHotwordMode(mode.HJ_Only); + if (hjModeToken && hjModeToken.activated) { + hjModeToken.activated.catch(() => { }); + } + } + catch (e) { + // ignore + } + }); + + Tunable.getButtonField('Simulate Hey Jibo', WIN).events.change.on(() => { + try { + embodied.listen.eventsIn.hjHeard.emit(); + process.nextTick(() => embodied.listen.eventsIn.oriented.emit()); + } + catch (e) { + // ignore + } + }); } } } @@ -639,6 +683,7 @@ const logs = require("../log"); const log = logs.listenLog; const USE_CENTER_ROBOT = false; const TIMEOUT = 3000; +const ENGAGE_HJ_FAILSAFE_TIMEOUT_MS = 6000; const ANIM_CLEAR_TIMEOUT = 'ANIM_CLEAR_TIMEOUT'; class EmbodiedListen extends jibo_state_machine_1.StateMachine { constructor(_ed) { @@ -820,9 +865,28 @@ class EmbodiedListen extends jibo_state_machine_1.StateMachine { switch (this._ambientMode) { case Types_1.AmbientListenMode.NORMAL: case Types_1.AmbientListenMode.NO_BODY: - Utils_1.Utils.setLED(this._jibo, Assets_1.Led.OFF); + Utils_1.Utils.setLED(this._jibo, Assets_1.Led.LISTENING); break; } + + // Immediate feedback: play perceptual eye transition/pose. + try { + const seePerson = !!(this._jibo && this._jibo.lps && this._jibo.lps.identity && this._jibo.lps.identity.getVisibleFaces && (this._jibo.lps.identity.getVisibleFaces().size > 0)); + const transitionAnim = Assets_1.AnimSelector.getPerceptualEyeTransition(seePerson, Assets_1.EyeTransitionStyle.POP, Assets_1.EyeTransitionDirection.TO, false); + const poseAnim = Assets_1.AnimSelector.getPerceptualEyePose(seePerson, true); + const animConfig = { + cache: jibo_cai_utils_1.CacheUtils.GlobalCacheName, + dofs: this.DOFS_EYE_AND_OVERLAY_MINUS_EYE_TRANSLATE, + }; + const animOptions = { + ownerInformation: EmbodiedListen.HJ_OWNER_INFORMATION, + }; + this._addAnimToQueue(transitionAnim, animConfig, animOptions); + this._addAnimToQueue(poseAnim, animConfig, animOptions); + } + catch (e) { + // ignore + } } }; this._nonHjExpression.addInternalTransition('ES Dispatch Done', this._engage); @@ -855,9 +919,24 @@ class EmbodiedListen extends jibo_state_machine_1.StateMachine { this._engage.addTypedEventTransition(this.eventsIn.cloudFinished, this._offExpression); this._engage.addTypedEventTransition(this.eventsIn.hjHeard, this._hjExpression); let nextBlinkTime = -1; + let engageFailsafe = null; this._engage.onEntry = () => { log.debug('Entering Engage'); nextBlinkTime = Date.now() + 2000; + if (engageFailsafe) { + clearTimeout(engageFailsafe); + } + engageFailsafe = setTimeout(() => { + try { + if (this.current === this._engage) { + Utils_1.Utils.setLED(this._jibo, Assets_1.Led.OFF); + this._engage.transitionTo(this._idle); + } + } + catch (e) { + // ignore + } + }, ENGAGE_HJ_FAILSAFE_TIMEOUT_MS); switch (this._ambientMode) { case Types_1.AmbientListenMode.NORMAL: break; @@ -872,6 +951,10 @@ class EmbodiedListen extends jibo_state_machine_1.StateMachine { } }; this._engage.onExit = () => { + if (engageFailsafe) { + clearTimeout(engageFailsafe); + engageFailsafe = null; + } switch (this._ambientMode) { case Types_1.AmbientListenMode.NORMAL: break;