我正在使用对话框流程为Google助手制作应用。我的应用程序使用部署在firebase上的webhook功能。主要问题是如何获取用户位置 - 我需要将坐标传递给URL。我可以提示消息获取位置权限,但是如何确认并获取坐标。
我是否需要添加任何确认意图?我要求默认欢迎意图中的位置许可。JEP 286: Scoping Choices
代码如下:
'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);
});
答案 0 :(得分:1)
是的,您需要一个Intent来处理来自用户的响应。 Dialogflow的模型是用户的所有响应都需要通过意图来处理。
在这种情况下,它将是您的“确认”意图。
您没有显示Intent的屏幕截图(如果您还有其他问题,请更新问题以包含它),但它需要处理事件actions_intent_PERMISSION
。处理此活动时,您不需要任何培训短语。
我拥有的一个(具有Intent名称和result.location
的动作)看起来像这样:
作为旁注,在您的处理程序中,您正在尝试获取用户名,但除非您要求获得权限,否则此名称不可用。你没有要求许可。如果你愿意,你可以在你用
之类的东西询问他们的位置时同意app.askForPermissions("To show your address", [
app.SupportedPermissions.NAME,
app.SupportedPermissions.DEVICE_PRECISE_LOCATION
]);
根据您的屏幕截图更新。
目前还不清楚你的谈话流程是什么,所以我做了一些假设。
但根据您的代码,您会因欢迎意图而要求获得许可。然后,用户授予权限,您需要一个接受该回复的意图。
我没有看到接受该回复的意图。
为了接受回复,您需要一个处理事件actions_intent_PERMISSION
的Intent,正如我在上面的屏幕截图中所示。
您似乎也在创建上下文,但目前尚不清楚原因。
根据您发布的代码和其他评论更新。
代码存在一些问题,可能会导致您遇到的一些问题,以及可能导致您将来遇到问题的其他一些问题。在评论和一些未提出的问题中回答您的一些问题:
我启用了Small Talk
这并没有伤害任何东西 - 但它可能也没有任何帮助。我建议你禁用它,直到你的对话的核心部分工作。
我可以获得坐标
好 - 所以Intent正在工作。
但是...
我看到你将坐标存储在一个全局变量中。这适用于这种情况(但不完全,请参阅您的下一个问题),但如果不止一个人正在使用该操作,则不会扩展,因为值可能会在用户会话之间混淆。
换句话说:如果您在webhook中使用全局变量,则每个人都可以访问这些值。这非常糟糕。
您想要的是一种在您的webhook调用之间存储用户信息的方法。有许多方法可以涵盖elsewhere并且可以参与其中。但是,一般情况下,您可以将值存储在上下文或app.data
中,并且它们将作为同一对话的一部分返回给您。
我第一次询问时,我没有收到目的地地址 和 当我第二次询问时,它有目的地地址
您的函数makeDirection()
包含一个异步操作来获取目标地址的纬度/经度,但是您要在该异步块之外发送回复。
所以会发生什么是启动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
是合法的,但试图将其拆分以获得特定值并非最佳做法,尤其是因为用户可能没有准确地说出您认为他们会说的内容。例如,如果他们说“我正朝着某个地方”会怎么样。
最好让你的direction_action
意图采用各种不同的短语,并将其中的“重要”部分(目的地)分配给参数。然后,在您的webhook中,您可以只读取参数的值并将其传递给服务以确定位置。
您还可以查看最近公布的Place Helper,它与设备精确位置助手类似,但也获取用户指定的地址。