How does Action on Google Smart Home API works Asynchronously? - actions-on-google

I recently developed a project on Amazon Alexa for Smart Home Skill API and We developed using Async Method. In Alexa there are Event Gateway to make post call Asynchronously and deffered response to keep event gateway open. I know that Action on Google has homegraph. Working of HomeGraph and EventGateway is it the same I was wondering?
I was also wondering how can I make the Execution Asynchronous for the Action on Google?
According to my understanding I'll be requiring to make a post call to Homegraph for that purpose.

Yes, you can make a POST to the home graph once the state is completely changed.
For certain types of devices, which may take a while to complete, you can return an execute response with a PENDING:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"commands": [{
"ids": ["123"],
"status": "PENDING",
"states": {
"on": false,
"online": true
}
}]
}
}
Later, once the status is correct, you can use the Report State API:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"agentUserId": "1234",
"payload": {
"devices": {
"states": {
"123": {
"on": true
},
}
}
}
}

Related

How to report state changes on devices over real-time feed for Smart Home apps?

Documentation for SYNC intent mentions that if willReportState property of a device is true, the device will report its state through Real Time Feed.
How do I write state updates to the Real Time Feed? I can't find any documentation on it.
The documentation to do it is available.
First you'll need to enable the HomeGraph API and obtain an API key. Then you should send a POST request to https://homegraph.googleapis.com/v1/devices:reportStateAndNotification with a JWT and the following payload:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"agent_user_id": "1234",
"payload": {
"devices": {
"states": {
"1458765": {
"on": true
},
"4578964": {
"on": true,
"isLocked": true
}
}
}
}
}

Actions on Google - smart home - how to make Google Home response properly when smart home device is offline?

My smart home app can control my smart home devices already.
However, I can't make Google Home to say like "your device is offline" when the smart home device is offline.
Google Home always says "ok, turning device_name on.".
According to the document and Node.js example provided by Google, I tried 2 kinds of error response:
{
"requestId": "xxxxxxx",
"payload": {
"commands": [{
"ids": ["456"],
"status": "ERROR",
"errorCode": "deviceoffline"
}]
}
}
{
"requestId": "xxxxxxx",
"payload": {
"commands": [{
"ids": ["456"],
"status": "OFFLINE",
"errorCode": "deviceoffline"
}]
}
}
But both are not working.
Please enlighten me. Thanks.
2017/08/02 update:
offline status is working on QUERY, like "Is device_name on?".
Not working on EXEC, like "Turn on device_name".
You missed out online parameter in the JSON. Here is an example of offline
{
"ids": ["456"],
"status": "ERROR",
"errorCode": "deviceTurnedOff",
"online": false
}

Simulator keeps replying that endpoint could not be called, while I see a POST request in the logs

I am currently writing an integration into Actions on Google using PHP. I have generated a action.json file with my test endpoint as the fulfillment. I use ngrok to expose my local development machine publicly.
Unfortunately the simulator keeps insisting that the app isn't responding. In the access logs, and the ngrok Inspector I do see that a request came in, and it has been neatly answered with a JSON reply.
In an act of pure desperation I even upload a JSON response, directly taken from the Fulfillment documentation page to a server and set that as the fulfillment URL. The result is the same, same error.
I do not see a way to get a more detailed error message from Actions on Google, explaining why it does not work.
My action.json:
{
"actions": [
{
"name": "MAIN",
"intent": {
"name": "actions.intent.MAIN"
},
"fulfillment": {
"conversationName": "development4"
}
},
{
"name": "TEXT",
"intent": {
"name": "actions.intent.TEXT"
},
"fulfillment": {
"conversationName": "development4"
}
}
],
"conversations": {
"development4": {
"name": "development4",
"url": "https:\/\/02c085c0.ngrok.io\/actionsongoogle\/process\/development4"
}
}
}
The json I response with:
{
"expectUserResponse": false,
"expectedInputs": [{
"inputPrompt": {
"richInitialPrompt": {
"items": [{
"simpleResponse": {
"textToSpeech": "hello"
}
}]
}
},
"possibleIntents": [{
"intent": ["actions.intent.TEXT"]
}]
}]
}
The result output in the Simulator then displays:
{
"response": "my test app isn’t responding right now. Try again soon.\n",
"audioResponse": "//NExAARq...",
"debugInfo": {
"sharedDebugInfo": [
{
"name": "ExecutionResponse",
"debugInfo": "Failed to call your endpoint."
}
]
},
"visualResponse": {}
}
Two things to investigate:
Check how long it is taking for the reply to be sent. Agents need to send a response back within about 5 seconds or the Assistant will time out and give the "not responding" message.
Check what the reply code being issued is. If you think you're sending something back, but your server actually crashes before an HTTP 200 response code is sent back with the body, the Assistant never gets the response. I've also seen it where people are thinking they're sending a response - but no response is actually sent at all.
Testing with curl or wget to your ngrok URL (so it makes a full round trip) might be able to help diagnose both of these.
The issue was in the returned JSON. I have set up the nodejs SDK and reply in the same way as the PHP cod will (a simple hello). The response generated by the NodeJS SDK is very different. Apparently the example that I used from the docs earlier is also invalid.
I advice anyone building their own implementation using Webhooks to first generate the desired response via de NodeJS sdk, the reference in the manual is not always clear (at least for me).
Response by NodeJS SDK:
{
"expectUserResponse": false,
"finalResponse": {
"speechResponse": {
"textToSpeech": "hello"
}
}
}
Implementation in SDK:
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res) {
let ActionsSdkApp = require('actions-on-google').ActionsSdkApp;
const actionsApp = new ActionsSdkApp({request: req, response: res});
//const inputPrompt = actionsApp.buildInputPrompt(false, 'hello')
actionsApp.tell('hello');
})
app.listen(80);

Wit.ai node package buggy

I was working with wit.ai today. I was using the node-wit module. But the responses I was acting were very weird.
When I used the node-wit module. I got the response as -
{
"msg_id": "0f4rOWRXQMIhVuf5i",
"_text": "what is your name",
"entities": {
"intent": [{
"confidence": 0.9425254893432,
"value": "get_name"
}]
}
}
Whereas when i used the cURL command to get the response the response was very different.
{
"msg_id": "0KJdIPedYbYwWOgOL",
"_text": "what do you do",
"entities": {
"intent": [{
"confidence": 0.97713342030998,
"value": "get_job"
}]
}
}
Can anyone tell why this is happening or if I am implementing the function wrong?
Are you using the same service, there are two services, one for conversations/stories and other for messages.
if that is not the reason try to check the context and take a look on the log section inside wit.ai web app

PayPal REST API: how to do an immediate payment and without asking for shipping address

I'm trying to use PayPal REST API instead of PayPal Classic API but it seems that the REST API is lacking two features that the Classic API has:
immediate payment: when the user goes to PayPal page show him a "Pay now" button instead of a "Continue" button and "You’re almost done. You will confirm your payment on ..." phrase.
no shipping address: avoid asking the user to confirm his shipping address while on PayPal page (in Classic API is done with NOSHIPPING=1 parameter, if I remember well)
So my question is: is it possibile do perform an immediate payment without asking for shipping address using REST API? Do I have to go back to Classic API?
I provide here a little more informations about how I'm using the PayPal REST API.
I'm using the PayPal REST Java SDK.
This is a sample request:
{
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [
{
"amount": {
"currency": "USD",
"total": "5",
"details": {
"subtotal": "5"
}
},
"description": "This is the payment transaction description.",
"item_list": {
"items": [
{
"quantity": "1",
"name": "Item 1",
"price": "5",
"currency": "USD"
}
]
}
}
],
"redirect_urls": {
"return_url": "http://XXX/handlePayment.jsp?guid\u003dXXX",
"cancel_url": "http://XXX/cancelPayment.jsp?guid\u003dXXX"
}
}
And its response:
{
"id": "XXX",
"create_time": "2014-06-29T08:52:55Z",
"update_time": "2014-06-29T08:52:55Z",
"state": "created",
"intent": "sale",
"payer": {
"payment_method": "paypal",
"payer_info": {
"shipping_address": {}
}
},
"transactions": [
{
"amount": {
"total": "5.00",
"currency": "USD",
"details": {
"subtotal": "5.00"
}
},
"description": "This is the payment transaction description.",
"item_list": {
"items": [
{
"name": "Item 1",
"price": "5.00",
"currency": "USD",
"quantity": "1"
}
]
}
}
],
"links": [
{
"href": "https://api.sandbox.paypal.com/v1/payments/payment/XXX",
"rel": "self",
"method": "GET"
},
{
"href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=XXX",
"rel": "approval_url",
"method": "REDIRECT"
},
{
"href": "https://api.sandbox.paypal.com/v1/payments/payment/XXX/execute",
"rel": "execute",
"method": "POST"
}
]
}
While delving through the REST API I came across this
I believe this means you don't have to go about creating any "Profiles" as such, and can just pass them along with the payment call...
Further explanation as requested :)
Below is an example of passing PayPal experience parameters along with a particular payment call using the Client-side JS method for Express checkout.
payment: function(data, actions) {
return actions.payment.create({
payment: {
transactions: [
{
amount: { total: '1.00', currency: 'USD' }
}
]
},
experience: {
input_fields: {
no_shipping: 1
}
}
});
},
Hope that makes enough sense to you guys! :)
Unfortunately, the REST API is still a long ways behind the Classic API with features it provides. These features you mentioned are things I've seen come up quite a bit, and to my knowledge they are not yet available with the REST services.
I personally have stuck with Classic as they provide everything and I really see no advantage to using REST myself. If you happen to be working with PHP (which I always do) you may be interested in my class library for PayPal. It makes all of the Classic API calls very quick and easy for you, and it's available on Packagist so you can use with Composer easily.
The REST API now supports no-shipping with the Payment Experience APIs.
You need to create a web experience profile and supply no_shipping as an input field. Then use the profile ID when creating the payment.
The profile ID doesn't need to be recreated every time.
appreciate that this post hasn't had any activity for a while but...
i hit on the exact same problem and used this post as a start point for my own question:
paypal api: take immediate payment without a shipping address
it's taken a bit of trial and error but i you can create a one off web profile with 'no_shipping' set to 1, store the id that it creates and then pass that in with future payments that don't require a shipping address.
still haven't figured out how to get rid of the 'You're almost done. You will confirm your payment on xxx.' but my payment process is a far better place than it was!
hope this helps someone out there as this no shipping issue is one that a lot of people appear to be hitting with the paypal api...
I tried using the experience section of the API and apart from still not being able to force a locale code have been able to disable shipping and go straight to billing:
payment: {
transactions: [{
invoice_number: document.getElementById("ReqTxt").value,
amount: {
total: document.getElementById("InvoiceAmt").innerText,
currency: document.getElementById("Currency").innerText
}
}]
},
experience: {
input_fields: {
no_shipping: 1
},
flow_config: {
landing_page_type:'billing'
}
}
you can also see this page. It is possible to set the user action in the flow_config section too
For 'Pay Now' instead of 'Continue' on Paypal I use a special param in approval url:
$approvalUrl = $payment->getApprovalLink().'&useraction=commit';
Result:
https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=TOKEN&useraction=commit