Ich baue eine Assistant -App für Google Home mit Dialogflow, Cloud-Funktionen und der neuen NodeJS-Client -Bibliothek V2 für Actions bei Google. Tatsächlich bin ich dabei, meinen alten mit V1 erstellten Code nach V2 zu migrieren.
Der Kontext
Ich versuche, den Standort des Benutzers anhand zweier getrennter Absichten abzurufen: Request Permission
(Absicht, die Berechtigungsanforderung an den Benutzer auslöst/sendet) und User Info
(Absicht, die prüft, ob der Benutzer die Berechtigung erteilt hat, und gibt dann die vom Assistenten angeforderten Daten zurück, um fortzufahren.
Die Angelegenheit
Das Problem ist, dass derselbe Code, der auf V1 problemlos funktioniert hat, nicht auf V2 funktioniert. Also musste ich ein bisschen umgestalten. Wenn ich meine Cloud-Funktion bereitstelle, kann ich erfolgreich die Erlaubnis des Benutzers anfordern, seinen Speicherort abrufen und dann eine externe Bibliothek verwenden (geocode
). Ich kann den Latlong in eine für Menschen lesbare Form konvertieren. Aber aus einigen Gründen (ich denke, es ist ein Versprechen) kann ich das Versprechen nicht auflösen und es dem Benutzer zeigen
Der Fehler
Ich erhalte den Fehler unten:
Der Code
Unten ist mein Cloud-Funktionscode. Ich habe mehrere Versionen dieses Codes ausprobiert, wobei die Bibliothek request
, https
usw. verwendet wurde. Kein Glück ... Kein Glück
const {dialogflow, Suggestions,SimpleResponse,Permission} = require('actions-on-google')
const functions = require('firebase-functions');
const geocoder = require('geocoder');
const app = dialogflow({ debug: true });
app.middleware((conv) => {
conv.hasScreen =
conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT');
conv.hasAudioPlayback =
conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT');
});
function requestPermission(conv) {
conv.ask(new Permission({
context: 'To know who and where you are',
permissions: ['NAME','DEVICE_PRECISE_LOCATION']
}));
}
function userInfo ( conv, params, granted) {
if (!conv.arguments.get('PERMISSION')) {
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded address on voice-activated speakers.
// Coarse location only works on voice-activated speakers.
conv.ask(new SimpleResponse({
speech:'Sorry, I could not find you',
text: 'Sorry, I could not find you'
}))
conv.ask(new Suggestions(['Locate Me', 'Back to Menu',' Quit']))
}
if (conv.arguments.get('PERMISSION')) {
const permission = conv.arguments.get('PERMISSION'); // also retrievable with explicit arguments.get
console.log('User: ' + conv.user)
console.log('PERMISSION: ' + permission)
const location = conv.device.location.coordinates
console.log('Location ' + JSON.stringify(location))
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
}
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
})
}
}
app.intent('Request Permission', requestPermission);
app.intent('User Info', userInfo);
exports.myCloudFunction = functions.https.onRequest(app);
Jede Hilfe wird sehr geschätzt. Vielen Dank
Sie haben die letzte Vermutung richtig - Ihr Problem ist, dass Sie keine Versprechen verwenden.
app.intent()
erwartet, dass die Handler-Funktion (in Ihrem Fall userInfo
) ein Promise zurückgibt, wenn async-Aufrufe verwendet werden. (Wenn nicht, können Sie mit nichts zurückkommen.)
Normalerweise verwenden Sie etwas, das ein Versprechen zurückgibt. Dies ist jedoch in Ihrem Fall schwierig, da die Geocode-Bibliothek nicht für die Verwendung von Promises aktualisiert wurde und Sie anderen Code verwenden, der in der Funktion userInfo
nichts zurückgibt.
Ein Umschreiben könnte in diesem Fall ungefähr so aussehen (den Code habe ich jedoch nicht getestet). Darin teile ich die beiden Bedingungen in userInfo
in zwei andere Funktionen auf, so dass eine Promise zurückgegeben werden kann.
function userInfoNotFound( conv, params, granted ){
// Note: Currently, precise locaton only returns lat/lng coordinates on phones and lat/lng coordinates
// and a geocoded address on voice-activated speakers.
// Coarse location only works on voice-activated speakers.
conv.ask(new SimpleResponse({
speech:'Sorry, I could not find you',
text: 'Sorry, I could not find you'
}))
conv.ask(new Suggestions(['Locate Me', 'Back to Menu',' Quit']))
}
function userInfoFound( conv, params, granted ){
const permission = conv.arguments.get('PERMISSION'); // also retrievable with explicit arguments.get
console.log('User: ' + conv.user)
console.log('PERMISSION: ' + permission)
const location = conv.device.location.coordinates
console.log('Location ' + JSON.stringify(location))
return new Promise( function( resolve, reject ){
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
reject( err );
} else {
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
resolve()
}
})
});
}
function userInfo ( conv, params, granted) {
if (conv.arguments.get('PERMISSION')) {
return userInfoFound( conv, params, granted );
} else {
return userInfoNotFound( conv, params, granted );
}
}
Dank @Prisoner konnte ich es funktionieren lassen. Ich musste meine Dialogflow-Struktur oder irgendetwas nicht ändern. Alles, was ich tun musste, war, den Reverse-Geocoding-Bereich in den Vorschlag von @Prisoner zu ändern. Und es hat für mich funktioniert.
//Reverse Geocoding
return new Promise( function( resolve, reject ){
// Reverse Geocoding
geocoder.reverseGeocode(location.latitude,location.longitude,(err,data) => {
if (err) {
console.log(err)
reject( err );
} else {
// console.log('geocoded: ' + JSON.stringify(data))
console.log('geocoded: ' + JSON.stringify(data.results[0].formatted_address))
conv.ask(new SimpleResponse({
speech:'You currently at ' + data.results[0].formatted_address + '. What would you like to do now?',
text: 'You currently at ' + data.results[0].formatted_address + '.'
}))
conv.ask(new Suggestions(['Back to Menu', 'Learn More', 'Quit']))
resolve()
}
})
});
Ich kann jetzt zu anderen Dingen übergehen!