Firebase 如何让用户确认Dialogflow中的位置和地理坐标?

Firebase 如何让用户确认Dialogflow中的位置和地理坐标?,firebase,webhooks,actions-on-google,dialogflow-es,Firebase,Webhooks,Actions On Google,Dialogflow Es,我正在使用对话流为谷歌助手制作应用程序。我的应用程序使用部署在firebase上的webhook功能。主要问题是如何获取用户位置-我需要将坐标传递给URL。我可以提示消息以获得位置许可,但是如何确认和获取坐标 我是否需要添加任何确认意图?我正在请求默认欢迎意图中的位置许可 代码如下: 'use strict'; process.env.DEBUG = 'actions-on-google:*'; const App = require('actions-on-google').Dialogfl

我正在使用对话流为谷歌助手制作应用程序。我的应用程序使用部署在firebase上的webhook功能。主要问题是如何获取用户位置-我需要将坐标传递给URL。我可以提示消息以获得位置许可,但是如何确认和获取坐标

我是否需要添加任何确认意图?我正在请求默认欢迎意图中的位置许可

代码如下:

'use strict';

process.env.DEBUG = 'actions-on-google:*';
const App = require('actions-on-google').DialogflowApp;

const functions = require('firebase-functions');



//----global variables-----
const http = require('https');
var body = "";
var body2="";
var address="";
var latitude="";
var longitude="";
var lati="";
var long="";


//------ADDRESS_ACTION to tell the current address based on current coordinates----
const ADDRESS_ACTION = 'address_action';

//-----DIRECTION_INTENT to output the map guidence through basic card------
const DIRECTION_INTENT = 'direction_action';

//--------during welcome intent, ask the permiisions------
const DIR_PERMISS_CONF= 'intent.welcome';

exports.addressMaker = functions.https.onRequest((request, response) => {
  const app = new App({request, response});
  console.log('Request headers: ' + JSON.stringify(request.headers));
  console.log('Request body: ' + JSON.stringify(request.body));


  function welcomeIntentDirection (app) 
  {
    app.askForPermission("Hi! Welcome to !To show address/direction",app.SupportedPermissions.DEVICE_PRECISE_LOCATION);
    if (app.isPermissionGranted()) 
    {
     // app.tell('You said ' + app.getRawInput());
    }
    else
    {
     // app.tell('You said ' + app.getRawInput());
    }

  }



function makeDirection(app)
{

  //-------here we are extraction what user said, we will extract the place name, it is for "direction to PLACE_NAME"-------

  var stringRequest=JSON.stringify(request.body);
  var jsonRequest=JSON.parse(stringRequest);
  var jsonSpeech=jsonRequest.originalRequest.data.inputs[0].rawInputs[0].query;
  var arr=jsonSpeech.split("to");
  var placeName=arr[1].trim();

  //------Current Location--------------
  let deviceCoordinates = app.getDeviceLocation().coordinates;
  latitude=deviceCoordinates.latitude;
  longitude=deviceCoordinates.longitude;



//-----now send this place name to api to get coordinates-----
 var req2= http.get("https://api.url-with-PARAMETER-placeName",function(res){

  res.on("data", function(chunk2){ body2 += chunk2;  });
  res.on('end', function()
  {
    if (res.statusCode === 200) 
    {
      var data2 = JSON.parse(body2);

      try
      {
          lati=data2.geometry.lat;
          long=data2.geometry.lng;
      }catch(e){app.tell("Invalid or non-existent address");}    
    }
  });
});


//-------------------Here BUILDING the CARD (Rich RESPONSE)-----------------------
  app.ask(app.buildRichResponse()
    // Create a basic card and add it to the rich response
    .addSimpleResponse('Your directions are here:')
    .addBasicCard(app.buildBasicCard()

      .addButton('Start Guidence', 'https://www.google.com/maps/dir/?api=1&origin='+latitude+','+longitude+'&destination='+lati+','+long+'')
      .setImage('https://png.pngtree.com/element_origin_min_pic/16/11/30/a535f05d9d512610e25a036b50da036f.jpg', 'Image alternate text')
      .setImageDisplay('CROPPED')
  )
);

}


  function makeAddress (app) 
      {
        let deviceCoordinates = app.getDeviceLocation().coordinates;
        latitude=deviceCoordinates.latitude;
        longitude=deviceCoordinates.longitude;
        var req=http.get("https://api.url/reverse?coords="+latitude+","+longitude+"", 
        function(res)
        {
          res.on("data", function(chunk){ body += chunk;  });

          res.on('end', function()
          {
            if (res.statusCode === 200) 
            {
                try 
                {
                  var data = JSON.parse(body);
                  address=data.words;
                  app.tell('Alright, your address is '+address);
                } catch (e) { }
            }
            else 
            {
              app.tell("Unable to contact to server +"+res.statusCode);
            }

          });

        });
      }

  // d. build an action map, which maps intent names to functions
  let actionMap = new Map();
  actionMap.set(DIR_PERMISS_CONF,welcomeIntentDirection);
  actionMap.set(ADDRESS_ACTION, makeAddress);
  actionMap.set(DIRECTION_INTENT, makeDirection);



app.handleRequest(actionMap);
});

是的,您需要一个意图来处理来自用户的响应。Dialogflow的模型是,用户的所有响应都需要通过一个意图来处理

在这种情况下,这将是您的“确认”意图

您不显示意图的屏幕截图(如果您还有其他问题,请更新问题以将其包括在内),但它需要处理事件
操作\u意图\u权限
。处理此事件时,您不需要任何培训短语

我拥有的一个(意图名称和动作为
result.location
)如下所示:

http.get("https://api.url-with-PARAMETER-placeName",function(res){

  res.on("data", function(chunk2){ body2 += chunk2;  });
  res.on('end', function(){
    if (res.statusCode === 200){
      var data2 = JSON.parse(body2);

      try{
        lati=data2.geometry.lat;
        long=data2.geometry.lng;
        app.ask( 
          app.buildRichResponse()
            .addThingsToRichResponse()
        );
      } catch(e){
        app.tell("Invalid or non-existent address");
      }
    }
  });
});

另一方面,在处理程序中,您试图获取用户名,但除非您请求允许,否则此名称不可用。你没有请求许可。如果你想,你可以在询问他们的位置的同时,通过类似的方式请求许可

app.askForPermissions("To show your address", [
  app.SupportedPermissions.NAME,
  app.SupportedPermissions.DEVICE_PRECISE_LOCATION
]);
根据屏幕截图更新

现在还不清楚你的对话流程是什么,所以我做了一些假设

但根据您的代码,您请求许可是出于欢迎目的。然后用户给予许可,您需要一个接受该回复的意图

我看不出有人愿意接受这个回答

为了接受回复,您需要一个意图来处理事件
actions\u Intent\u PERMISSION
,如我在上面的屏幕截图中所示

您似乎也在创建上下文,尽管原因尚不清楚

根据您发布的代码和其他评论更新

代码中有几个问题可能会导致您遇到的一些问题,还有一些其他问题可能会在将来给您带来问题。要回答评论中的一些问题和一些未询问的问题,请执行以下操作:

我启用了聊天功能

这并没有伤害到任何东西,但可能也没有任何帮助。我建议你禁用它,直到你的谈话的核心部分开始工作

我可以得到坐标

好-所以意图是有效的

但是

我看到你将坐标存储在一个全局变量中。这种方法在这种情况下有效(但不完全有效,请参见您的下一个问题),但如果有多人在使用该操作,则无法扩展,因为这些值可能在用户会话之间混淆

换句话说:如果在webhook中使用全局变量,每个人都可以访问这些值。这很糟糕。

您需要的是一种在调用webhook之间存储用户信息的方法。有许多方法可以做到这一点,这些方法都包含在本文中,并且可能涉及到很多方面。但是,通常情况下,您可以将值存储在上下文或
app.data
中,它们将作为同一对话的一部分返回给您

我第一次问的时候没有目的地地址 和 当我第二次询问时,它有目的地地址

函数
makeDirection()
包含一个异步操作,用于获取目标地址的lat/lon,但是您将在异步块之外发回应答

因此,所发生的情况是,您启动http调用,然后代码继续,并将应答发送给目标为空的用户。在稍后的某个时刻,回调完成并设置了目标,但对于第一次调用来说太晚了。但是,当您第二次调用它时,它会执行相同的例程(启动异步调用,然后在调用完成之前立即发送回一些内容),但是上一次运行的值是设置的,因为您在全局变量中设置了它们

要解决此问题,您需要调用
app.ask()
,作为异步回调的一部分。这可能看起来像这样:

http.get("https://api.url-with-PARAMETER-placeName",function(res){

  res.on("data", function(chunk2){ body2 += chunk2;  });
  res.on('end', function(){
    if (res.statusCode === 200){
      var data2 = JSON.parse(body2);

      try{
        lati=data2.geometry.lat;
        long=data2.geometry.lng;
        app.ask( 
          app.buildRichResponse()
            .addThingsToRichResponse()
        );
      } catch(e){
        app.tell("Invalid or non-existent address");
      }
    }
  });
});
获取用户对目的地所说内容的问题

您试图获取用户目的地的代码是。。。奇怪的获取
rawInputs
是合法的,但尝试将其拆分以获取特定值并不是最佳做法,尤其是因为用户可能无法准确说出您认为他们将要说的内容。例如,如果他们说“我要去某个地方”会怎么样

更好的方法是让您的
方向\u操作
意图使用各种不同的短语,并将其中的“重要”部分(目标)指定给一个参数。然后,在webhook中,您可以只读取参数的值,并将其传递给服务以确定位置


您可能还想看一看最近发布的,类似于设备精确定位助手,但也可以获得用户指定的地址。

先生,您可以制作一个“名字通灵”的视频教程吗?我想届时我所有的疑问都会得到澄清。当我对位置权限说“是”时,在请求中它得到了更新,我能够获得位置,但google助手回答“你能再说一遍吗”或“我不明白”。这表明你触发了回退意图,这意味着它不符合任何其他意图。用屏幕截图更新您的问题,说明您认为应该处理的意图,这可能有助于我们进一步帮助您。请稍等,回答已更新。但是(1) 我们不是在你的另一个问题中讨论过异步函数吗?(2) 如果将它们存储在局部变量中,则多个用户可以访问