首页 > 解决方案 > 如何让对话流谷歌代理响应并确认 Firebase 的字段更改

问题描述

'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const {WebhookClient} = require('dialogflow-fulfillment');

process.env.DEBUG = 'dialogflow:*'; // enables lib debugging statements

admin.initializeApp({
    credential: admin.credential.applicationDefault(),
    databaseURL: "https://my_db.firebaseio.com/",
});

var database = admin.database();
var transition = database.ref('/stage');


exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
    console.log('Inside :) yessssssss !');
    const agent = new WebhookClient({ request, response });


    function moveToStage (agent) {
        transition.set('2');
        agent.add('Welcome to xx console. Please accept the notification on your watch');
    }


    transition.on('value', (snapshot) => {
        console.log("Reading value succesfully from firebase");
        console.log(snapshot.val());
        if(snapshot.val() == '3'){
            agent.add('Thank you for granting me the access.');
            // OR
            // response.setHeader('Content-Type','applicaiton/json');
            // response.send(JSON.stringify({"fulfillmentText": 'Thank you for granting me the access.'}));
        }
    });


    let intentMap = new Map();
    intentMap.set('welcome_and_ask_to_sync', moveToStage);
    agent.handleRequest(intentMap);
});

我有一个意图welcome_and_ask_to_sync,它已激活 webhook。当该 Intent 被成功的语音输入触发时,它会以来自代理的文本/语音进行响应,并更新stage相应 firebase 数据库中的字段。

现在,在某些情况下,另一个外部应用程序会更新stagefirebase 数据库中的该字段。

没有这部分在履行代码中,有变化

transition.on('value', (snapshot) => {
    console.log("Reading value succesfully from firebase");
    console.log(snapshot.val());
    if(snapshot.val() == '3'){
        agent.add('Thank you for granting me the access.');
        // OR
        // response.setHeader('Content-Type','applicaiton/json');
        // response.send(JSON.stringify({"fulfillmentText": 'Thank you for granting me the access.'}));
    }
});

这里的目的是让 google home 说出一些东西,比如在这种情况下Thank you for granting me the access.

注意: 我不需要被解雇的意图(抱歉之前的混淆)。我只需要谷歌家庭语音代理来确认这个变化/触发。

现在,当我查看日志时,我发现它在这里中断了agent.add('Thank you for granting me the access.');

而 err log si 有点像:

Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:356:11) at transition.on (/user_code/index.js:36:22) at /user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:4465:22 at exceptionGuard (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:691:9) at EventList.raise (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:9727:17) at EventQueue.raiseQueuedEventsMatchingPredicate_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:9681:41) at EventQueue.raiseEventsForChangedPath (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:9665:14) at Repo.onDataUpdate_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:12770:26) at PersistentConnection.onDataPush_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:12070:18) at PersistentConnection.onDataMessage_ (/user_code/node_modules/firebase-admin/node_modules/@firebase/database/dist/index.node.cjs.js:12064:18)

所以基本问题仍然存在: 如何让代理说出/更新文本响应并确认该数据库的字段更改。

标签: firebasefirebase-realtime-databasedialogflow-esactions-on-google

解决方案


简短的回答是你不能——当然不是你这样做的方式。

将响应从您的 webhook 发送回 Dialogflow 后,HTTPS 连接将关闭,任何进一步的回复都会生成您看到的错误。

此外,AoG 和 Dialogflow 使用的对话模型是用户必须始终发起每一轮对话。在这一点上,AoG 不可能“宣布”某事。这将被认为有点侵入性。

您可以通过 Google 上的 Actions 发送通知,当用户确认通知时会重新开始对话。但是,通知只会发送到智能手机,而不是扬声器。所以这可能无法满足您的需求。

如果您希望在初始发送后很快发生一些更新,您可能想看看是否可以在等待更多更新时使用“媒体响应”来保持对话继续进行。当“保持音乐”结束时,它会向你的 Action 发送一个事件,你可以重新开始保持音乐或回复。在这种情况下,您不会使用该.on()方法进行更新,但必须在每次媒体播放完毕时检查是否有未发送的更新。


推荐阅读